Fortran Coder

标题: C调用Fortran的混编 [打印本页]

作者: andy8496    时间: 2017-9-29 22:14
标题: C调用Fortran的混编
因为某些很特殊的需要,需要实现C调用Fortran的静态链接库生成C的动态链接库(怎么会有这么奇葩的需求?)
之前做过C调用Fortran的Dll,还算顺利,但是这个好久没搞定。
请大侠指点!

附件:VS2012+IVF2015

ForLib.part01.rar

1.91 MB, 下载次数: 24

ForLib.part02.rar

1.61 MB, 下载次数: 17


作者: fcode    时间: 2017-9-30 07:39
你就是用这种混编方式?太老土了,而且没有扩展性。强烈建议你用 ISO_C_binding 进行。
作者: fcode    时间: 2017-9-30 08:12
试试标准的 ISO_C_binding 用法:

[Fortran] 纯文本查看 复制代码
module ForLib
  use , intrinsic :: ISO_C_Binding
  implicit none
contains

  subroutine sub_test(ps,ii,pia,oo) Bind(C,Name="sub_test")
    type(C_PTR) , value :: ps , pia
    character(len=512) , pointer :: s
    integer , pointer :: ia(:)
    integer :: ii,oo
    call c_f_pointer( pia , ia , [100] )
    call c_f_pointer( ps , s )
    oo = len(s)+sum(ia)-ii
    write(789,*) s
  end subroutine sub_test

end module ForLib


[C] 纯文本查看 复制代码
#pragma optimize("g",off)

void sub_test(char *, int *, int *, int *);

__declspec(dllexport) void ccf_test(int *oo){
  int ooa = 64;
  char s[512] = "helllo,world";
  int ii = 32;
  int ia[100];   
  for (int i = 0; i < 100; i++){
    ia=3;
  }
  oo = &ooa;
  sub_test(&s, &ii, &ia[0], oo);
  
}

作者: andy8496    时间: 2017-10-9 21:21
可以了!多谢!
看来这个ISO_C_Binding真要好好看看了。
作者: andy8496    时间: 2017-10-9 22:21
多问一句,如果我Fortran中作为输入参数的字符串长度不定,这里又该如何声明:
character(len=512) , pointer :: s

call c_f_pointer( ps , s )


作者: fcode    时间: 2017-10-10 08:27
一般来说,定义得足够长就可以了。因为是虚参,所以并不会占用过多内存空间。
其意义就像:“我以为它有512字节,实际上它不到512字节”
由于C语言字符串以 \0 结尾,所以不能直接对 s 进行 // 等操作。如果需要的话,可以对 s 复制一份后进行。

初次之外,C语言也可以把大小传递给fortran,但是这样会多一个参数。
ccf_test( char *p , int n);

subroutine ccf_test( ps , n )
  character(len=n) , pointer :: s
  call c_f_pointer( ps , s )
作者: andy8496    时间: 2017-10-10 16:31
好的 再次感谢。
作者: andy8496    时间: 2017-10-14 20:56
fcode 发表于 2017-10-10 08:27
一般来说,定义得足够长就可以了。因为是虚参,所以并不会占用过多内存空间。
其意义就像:“我以为它有512 ...

又遇到一个问题:
现在用Fortran创建静态链接库A.lib,其中的一个子程序F调用了已有的Fortran写的Dll中的子程序B,编译成功

(因为B在Module中,开始将Fortran的Dll对应的.lib添加到A.lib工程的source file中编译并不成功,提示 Error in opening the compiled module file.  Check INCLUDE paths.。后来发现,将dll对应的.mod文件复制到A.lib的工程中目录中即可,甚至都不需要添加Fortran的Dll对应的.lib添加到A.lib的source file即可成功)

然后用C语言创建C.Dll,调用了A.lib中的F,采用的是将A.lib添加到C.dll的source file中,提示B无法解析:
A.lib(A.obj) : error LNK2001: 无法解析的外部符号 B

这个要如何操作才能成功呢?
作者: vvt    时间: 2017-10-15 16:52
把 Fortran DLL 对应的 .lib 添加到 C.dll 工程中。
作者: pasuka    时间: 2017-10-16 15:57
在有Fortran代码的前提下,通过添加ISO_C_BINDING相关申明,为啥就不能编译生成C可以直接调用的静态与动态链接库呢?




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2