gfortran、DLL、下划线

发布于 2024-08-16 07:40:21 字数 696 浏览 5 评论 0 原文

我想从第三方 DLL 访问一些子例程。这些函数使用 STDCALL 作为调用约定。

运行 dumpbin /export foo.dll 会给我类似的结果:

      ...
      7    6 00004B40 Foo@16
      ...

我使用以下方法编译代码:

      gfortran test.f90 -o test.exe -Wl,foo.dll

我收到错误:对 '_foo_' 的未定义引用(注意下划线)。

我尝试添加 -mrtd 编译标志,以及我用谷歌搜索的其他标志,但都无济于事。

如何告诉 fortran 不添加下划线?


编辑: 需要进行一些澄清。

  1. 我有一个现有的 DLL,但没有源代码。
  2. 如果有帮助的话,此 DLL 是用 Visual Basic 编写的。
  3. 我想 fortran 调用这个DLL。
  4. 当我在 test.f90: Foo(1.0d0) 中写入时,出现 undefined reference to '_foo_' 链接错误

I want to access some subroutines from a third party DLL. The functions use STDCALL as the calling convention.

Running dumpbin /export foo.dll gives me something like:

      ...
      7    6 00004B40 Foo@16
      ...

I compile my code using:

      gfortran test.f90 -o test.exe -Wl,foo.dll

I get an error: undefined reference to '_foo_' (note the underscores).

I have tried adding the -mrtd compilation flag, as well as other flags I googled, all to no avail.

How can I tell fortran to not add the underscores?


edit: A bit of clarification is in order.

  1. I have an existing DLL to which I do not have the source to.
  2. This DLL is written in Visual Basic, if it helps.
  3. I want to call this DLL from fortran.
  4. When I write in test.f90: Foo(1.0d0) I get an undefined reference to '_foo_' linkage error

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

机场等船 2024-08-23 07:40:22

另一种方法是使用 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

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.

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
装纯掩盖桑 2024-08-23 07:40:21

您尝试过 -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.

山川志 2024-08-23 07:40:21

您需要将 ISO_C_BINDING 的使用与编译器属性结合起来。您确实应该阅读混合语言编程 gfortran 手册的部分。它提供了很好的建议,也可以与其他编译器一起使用。特别是,在您的情况下,您需要 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 的行,它应该使其正常工作。

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:

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

Notice the line with stdcall, it's what should make it work.

月亮是我掰弯的 2024-08-23 07:40:21

只是想扩展 MSB 的 -fno-underscoring 答案:如果使用 f2c 和g77。来自 gfortran 文档

随着 -fundersscoring 的生效,GNU
Fortran 附加一个下划线
不带下划线的外部名称。
这样做是为了确保兼容性
包含许多 UNIX 生成的代码
Fortran 编译器。

警告:GNU 的默认行为
Fortran 与 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()

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:

With -funderscoring in effect, GNU
Fortran appends one underscore to
external names with no underscores.
This is done to ensure compatibility
with code produced by many UNIX
Fortran compilers.

Caution: The default behavior of GNU
Fortran is incompatible with f2c and
g77, please use the -ff2c option if
you want object files compiled with
GNU Fortran to be compatible with
object code created with these tools.

Use of -fno-underscoring is not
recommended unless you are
experimenting with issues such as
integration of GNU Fortran into
existing system environments
(vis-à-vis existing libraries, tools,
and so on).

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:

#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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文