English 中文(简体)
gfortran, DLL, underscore
原标题:

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
问题回答

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.

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.

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()

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




相关问题
What form is DLL & what makes it processor dependent

I know DLL contains one or more exported functions that are compiled, linked, and stored separately.. My question is about not about how to create it.. but it is all about in what form it is stored.. ...

Create Visual Fox Pro DBF with activex

any one knows if there is a activex dll that can create VFP DBF files? I mean im writing app with 1C:Enterprise 8.2 language, and i need to export some datas into VFP DBF. And i can only use activex ...

Dynamically loading a dll in C#

I have a window to use for editing. The editor should load a dll (which I have full control of) in response to the user s selection to know how to display the information visually. (They re dll s, as ...

How do I link to a DLL from javascript in XULRunner?

I have a dll (that I didn t write) and I would like to use it in an XULRunner application. I know nearly nothing about this, so bear with me. Apparently I can use XPCOM to load the dll and then call ...

Is there a minimal php5ts.dll?

I ve completed my web app and am using mongoose to serve the php pages. The whole app & mongoose is less then 2MB. The php5ts.dll is almost 5MB so that really adds bloat. Also, my app is very ...

DllGetVersion not giving expected results under Windows 7

I have some code that attempts to test whether my application is running with the themes set. Here s the C# code: internal class NativeMethods { [DllImport("comctl32", CharSet = CharSet.Auto, ...

How to restrict access to my DLL

Is possible to restrict access to my .NET DLL library? My application has more EXE assemblies and I need share some code, but I don t want someone else could use that.

Creating a thread in DllMain?

It seems that when a thread is created from within DllMain upon DLL_PROCESS_ATTACH it won t begin until all dll s have been loaded. Since I need to make sure the thread runs before I continue, I get a ...

热门标签