2

我在 Fortran 和 C“master”中有以下代码。它提供了 sigsegv,但我不明白为什么。它应该从主 C 程序中获取一个指针,将其转换为 Fortran 指针格式,并读出 C 指针指向的数据。没什么特别的,但仍然是 SigSegv。顺便说一句,这是我看到的唯一方法来规避 Fortran 多维数组与...之间缺乏互操作性(是的,C 没有多维数组)。

Fortran 部分:

module ret
    implicit none
    integer, pointer :: a(:,:)
end module ret

module func
    implicit none
    contains

    subroutine initialize(cp) bind(c,name='initialize')
        use ret
        use iso_c_binding
        implicit none
        type(c_ptr) :: cp

        call c_f_pointer(cp,a,[5,5])

    end subroutine initialize

    subroutine printa bind(c,name='printa')
       use ret
       implicit none
       integer :: i,j

       do i=1,5
         do j=1,5
            print *,i,j,a(i,j)
         end do
       end do
    end subroutine printa
end module func

C部分:

#include<stdio.h>
void initialize( void *);
void printa();

int main()
 {    
  int *tab;
  tab = (int *)malloc(25 * sizeof (int *));
  int i;
  for(i=0;i<25;++i)
   tab[i]=i;
  initialize(tab);
  printa();
  printf("ok\n");
  return 0;
 }

SIGSEGV 出现在print *,i,j,a(i,j)Fortran 部分的行

编辑:我已将 "integer*8" 改回 "integer" 并改do i=1,10do i=1,5. 对于这个版本,问题仍然有效

i=1 和 j=1 时出现 SIGSEGV

4

1 回答 1

3

我将其添加为答案,以防其他人遇到与您类似的问题。

显示的代码中有两个问题。首先,正如 Klas Lindbäck 所说,您正在为整数指针分配内存。这不是问题的根源,因为指针的大小至少int等于或大于该大小,但仍应向sizeof操作员提供正确的数据类型,以防止过度使用可用资源。

第二个问题是在 Fortran 中,参数是通过引用传递的。这意味着当从 C 调用 Fortran 例程时,应该使用地址运算符。&常量也应该放在单独的常量变量中,并通过地址传递。纠正前面的问题后,C 代码应该是:

tab = malloc(25 * sizeof (int)); // int instead of int *
int i;
for(i = 0; i < 25; ++i)
  tab[i] = i;
initialize(&tab);                // pass tab by address

Fortran 2003 引入了VALUE可应用于虚拟例程参数的属性,以使它们改为按值传递。如果您的 Fortran 编译器实现了这个 F2003 功能,那么您可以将cpdummy 参数的声明更改initialize为:

type(c_ptr), value :: cp

如果你这样做,你就不需要tab通过引用传递。

于 2012-12-14T17:06:06.637 回答