我想从第三方DLL访问一些子程序。这些函数使用STDCALL作为调用约定。
正在运行dumpbin /export foo.dll
给我的内容如下:
...
7 6 00004B40 Foo@16
...
我使用以下代码编译代码:
gfortran test.f90 -o test.exe -Wl,foo.dll
我收到错误:undefined reference to '_foo_'
(请注意下划线)。
我尝试添加-mrtd
编译标志,以及我用Google搜索的其他标志,都无济于事。
如何告诉fortran不添加下划线?
编辑:按顺序进行一些澄清。
Foo(1.0d0)
我收到undefined reference to '_foo_'
链接错误答案 0 :(得分:3)
您是否尝试过-fno-underscoring?
我在http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html(接近结尾)发现了Tobias Burnus(一个gfortran开发人员)的帖子 - 他建议使用编译器指令而不是-mrtd。
答案 1 :(得分:2)
您需要将ISO_C_BINDING与编译器属性结合使用。你应该真正阅读gfortran手册的Mixed-Language Programming部分。它提供了可以与其他编译器一起使用的好建议。特别是,在您的情况下,您需要stdcall
属性:
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
!GCC$ ATTRIBUTES stdcall :: foo
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs
注意stdcall
行,它应该使它起作用。
答案 2 :(得分:1)
只想展开M.S.B's -fno-underscoring answer:如果使用f2c& G77。来自the gfortran documentation:
-funderscoring生效,GNU Fortran附加一个下划线 外部名称没有下划线。 这样做是为了确保兼容性 使用许多UNIX生成的代码 Fortran编译器。
警告:GNU的默认行为 Fortran与f2c和f2c不兼容 g77,如果是,请使用-ff2c选项 你想要用。编译的目标文件 GNU Fortran兼容 用这些工具创建的目标代码。
使用-fno-underscoring不是 建议除非你是 试验诸如此类的问题 将GNU Fortran集成到 现有的系统环境 (相对于现有的图书馆,工具, 等等。)
您可能需要使用-fno-underscoring
之类的内容重新编译DLL,以从DLL中删除下划线。
我遇到某些Fortran编译器与下划线前缀/后缀相关的可移植性问题:默认情况下有些编译器_prefix或suffix_,而其他编译器没有!我的解决方案是预处理器指令:
#ifdef LC_UNSC
#define GET_DIP_MOMENT get_dip_moment_
#elif LC_NOUNSC
#define GET_DIP_MOMENT get_dip_moment
#endif
...
call GET_DIP_MOMENT()
答案 3 :(得分:0)
另一种方法是使用Fortran 2003的ISO C绑定,gfortran> = 4.3支持。这将自动使用C的强调约定(即,可能没有),而不是Fortran编译器的约定。如果Windows链接器关心它,它还可以控制子例程名称的大小写(大小写)。 Fortran不区分大小写,因此您可以通过任何方式调用Fortran子例程 - 可能是链接器转换为小写。
在调用“Foo”的Fortran例程的声明中包含以下“接口”,将Foo描述为具有双类型的单个参数的C子例程(void函数) - Fortran输入/输出或指针C.如果Foo有其他属性,则需要更改接口。 “bind”子句指定要提供给链接器的区分大小写的名称。如果从几个Fortran例程调用Foo,那么最好将接口放入一个模块并从每个Fortran例程中“使用”它。
这适用于C - 也许它适用于Visual Basic。 ISO C绑定提供了很多控制,所以如果这不起作用,可能会有一些变化。
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs