【问题标题】:EXC_BAD_ACCESS when calling Fortran function from C从 C 调用 Fortran 函数时的 EXC_BAD_ACCESS
【发布时间】:2012-12-17 09:38:33
【问题描述】:

我环顾四周,虽然有很多 EXC_BAD_ACCESS 问题,但都没有帮助。

我正在使用 Mountain Lion(我认为是 OSX 10.8?)和 PGI 12。

我似乎无法从 C 中调用 fortran 函数,我写了一个简化的案例,似乎无法传递整数。

我的fortran函数是:

  1 integer function smallFortran(a) result(res) bind(c,name='smallFortran_')
  2 !integer function smallFortran(a) result(res)
  3     
  4     use ISO_C_BINDING
  5     implicit none
  6     
  7     integer(kind=c_int), intent(IN) :: a
  8     !integer, intent(IN) :: a
  9     
 10     print *,'A = ', a
 11     res = a;
 12 
 13 endfunction smallFortran

而我的 C 函数是,

int main() {
   int ier=7;
   ier = smallFortran_(8);
}

构建它..

matt@pontus:diffFst$ make                                                                                                               
pgcc -c cDoDiffFst.c                                                                                                                    
PGC-W-0267-#warning --  "Unsupported compiler detected" (/usr/include/sys/cdefs.h: 81)                                                  
PGC/x86-64 OSX 12.9-0: compilation completed with warnings                                                                              
pgcc -g -O0 -traceback -o cDoDiffFst cDoDiffFst.o smallFortran.o -lpgf90 -lpghpf2 -lpgf90rtl -lpgftnrtl -lpghpf_rpm

(我希望警告不是导致我的问题的原因,PGI user forum 对此作出回应,称他们将发送文件的更新版本,但我还没有得到回复。不知道为什么PGI 需要指定很多额外的库)

当我在调试器中运行它时..

matt@pontus:diffFst$ gdb cDoDiffFst                                                                                                     
(gdb) run
Starting program: /Users/matt/aurams/trunk/utils/diffFst/cDoDiffFst 
Reading symbols for shared libraries +............................. done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100001906 in _smallFortran_ (a=Cannot access memory at address 0x8
) at smallFortran.f90:10
10              print *,'A = ', a
(gdb)

我完全迷路了,为什么我不能发送一个 int?我试过给一个整数赋值并发送它,没有骰子。我已经将其作为子例程进行了尝试,我已经尝试过没有返回值.. 没有任何效果。

【问题讨论】:

  • 有很多事情可能出错.... 一个是 C 和 Fortran 通常使用不同的参数传递协议 -- C 是按值传递的,而 Fortran 通常是(取决于编译器和其他问题)参考。
  • @HotLicks - 嗯,没想到那样。也许我可以尝试将 int 作为参考传递? (我的 C 不好,我会尝试作为指针,并通过引用)

标签: c fortran fortran-iso-c-binding


【解决方案1】:

这是一个替代解决方案,展示了如何编写 Fortran 以匹配问题的原始 C。关键是声明中的value 限定符。使用 Fortran ISO C 绑定,您可以匹配 C 传递参数的各种方式。您还可以取消例程名称中的下划线......这是bindname 关键字的目的。

调用中不带下划线的C代码:

int main() {
   int ier=7;
   ier = smallFortran (8);
}

和匹配的 Fortran:

function smallFortran(a) result(res) bind(c,name='smallFortran')

     use ISO_C_BINDING
     implicit none

     integer(kind=c_int), intent(IN), value :: a
     integer(kind=c_int) :: res

     print *,'A = ', a
     res = a;

 endfunction smallFortran

【讨论】:

    【解决方案2】:

    错误应该说明出了什么问题; smallFortran_ 期望它的参数通过引用传递(就像 fortran 中的所有参数一样——注意我在这里有点快和松散),并尝试访问指针 8 处的数据,但失败了。修复很容易;该函数需要一个指针,所以给它一个:

    int main() {
      int ier = 7;
      int arg = 8;
      ier = smallFortran_(&arg);
    }
    

    这假设 fortran integer 类型对应于带有问题编译器的 C int;否则,您可能需要将 arg 设为 long

    【讨论】:

    • @hotLicks 评论让我注意到(现在看起来很明显,但我完全错过了。)谢谢!我现在正在尝试,并将发布我的结果。 (为此苦苦挣扎了一段时间,所以很高兴得到回应。而且我不擅长 C 并且不熟悉混合 C 和 fortran,所以这可能是我没有注意到的原因。:()谢谢!
    猜你喜欢
    • 2016-03-25
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多