gfortran、DLL、下划线
我想从第三方 DLL 访问一些子例程。这些函数使用 STDCALL 作为调用约定。
运行 dumpbin /export foo.dll 会给我类似的结果:
...
7 6 00004B40 Foo@16
...
我使用以下方法编译代码:
gfortran test.f90 -o test.exe -Wl,foo.dll
我收到错误:对 '_foo_' 的未定义引用
(注意下划线)。
我尝试添加 -mrtd
编译标志,以及我用谷歌搜索的其他标志,但都无济于事。
如何告诉 fortran 不添加下划线?
编辑: 需要进行一些澄清。
- 我有一个现有的 DLL,但没有源代码。
- 如果有帮助的话,此 DLL 是用 Visual Basic 编写的。
- 我想从 fortran 调用这个DLL。
- 当我在 test.f90:
Foo(1.0d0)
中写入时,出现undefined reference to '_foo_'
链接错误
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
另一种方法是使用 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 绑定提供了很多控制,因此如果这不起作用,也许一些变体可以。
A different approach is to use the ISO C Binding of Fortran 2003, which is supported by gfortran >= 4.3. This will automatically use the underscoring conventions of C (i.e., probably none), rather those of the Fortran compiler. It will also give you control over the case (capitalization) of the subroutine names, if the Windows linker cares about that. Fortran is case insensitive, and so you can call Fortran subroutines by any case -- probably the linker is converting to lower case.
Including the following "interface" in the declarations of the Fortran routine that calls "Foo" describes Foo to be a C subroutine (void function) with a single argument of double type -- Fortran input/output, or a pointer in C. If Foo has other properties, the interface needs to be changed. The "bind" clause specifies the case-sensitive name to provide to the linker. If you call Foo from several Fortran routines, then it is best to put the interface into a module and "use" it from each Fortran routine.
This is intended for C -- maybe it will work for Visual Basic. The ISO C Binding gives a lot of control, so if this doesn't work, maybe some variation will.
您尝试过 -fno-下划线 吗?
我在 http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html(接近尾声)——他建议使用编译器指令而不是 -mrtd。
Did you try -fno-underscoring ?
I found a post by Tobias Burnus (a gfortran developer) at http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html (near the end) -- he recommends the use of compiler directives instead of -mrtd.
您需要将 ISO_C_BINDING 的使用与编译器属性结合起来。您确实应该阅读混合语言编程 gfortran 手册的部分。它提供了很好的建议,也可以与其他编译器一起使用。特别是,在您的情况下,您需要
stdcall
属性:请注意带有
stdcall
的行,它应该使其正常工作。You need to combine the use of ISO_C_BINDING with compiler attributes. You should really read the Mixed-Language Programming section of the gfortran manual. It gives good advice that can be used with other compilers as well. In particular, in your case you need the
stdcall
attribute:Notice the line with
stdcall
, it's what should make it work.只是想扩展 MSB 的 -fno-underscoring 答案:如果使用 f2c 和g77。来自 gfortran 文档:
您可能需要使用
-fno-underscoring
之类的内容重新编译 DLL,以从 DLL 中删除下划线。我遇到了与某些 Fortran 编译器的下划线前缀/后缀相关的可移植性问题:某些编译器默认为 _prefix 或 suffix_ ,而其他编译器则不然!我的解决方案是预处理器指令:
Just wanted to expand on M.S.B's -fno-underscoring answer: You may run into issues if using f2c & g77. From the gfortran documentation:
You might need to recompile the DLL with something like
-fno-underscoring
to remove the underscores from the DLL.I've run into portability issues related to underscore prefix/suffix by certain Fortran compilers: Some compilers _prefix or suffix_ by default, while others don't! My solution has been preprocessor directives: