1

我想从第三方 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编译标志,以及我用谷歌搜索的其他标志,但都无济于事。

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


编辑:有点澄清是为了。

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

4 回答 4

5

你试过 -fno-underscoring 吗?

我在http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html找到了 Tobias Burnus(gfortran 开发人员)的帖子(接近尾声)——他建议使用编译器指令而不是 -mrtd。

于 2009-12-31T16:50:44.933 回答
3

您需要将 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,它应该使它起作用。

于 2010-01-16T14:22:02.307 回答
1

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()
于 2009-12-31T17:21:24.713 回答
0

另一种方法是使用 Fortran 2003 的 ISO C 绑定,gfortran >= 4.3 支持该绑定。这将自动使用 C 的下划线约定(即可能没有),而不是 Fortran 编译器的下划线约定。如果 Windows 链接器关心它,它还可以让您控制子例程名称的大小写(大写)。Fortran 不区分大小写,因此您可以在任何情况下调用 Fortran 子例程——可能链接器正在转换为小写。

在调用“Foo”的 Fortran 例程的声明中包含以下“接口”,将 Foo 描述为具有单个 double 类型参数的 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
于 2010-01-03T22:46:06.307 回答