首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用gfortran的加载库和getprocaddress?

如何使用gfortran的加载库和getprocaddress?
EN

Stack Overflow用户
提问于 2013-01-04 22:09:49
回答 1查看 4.6K关注 0票数 0

我正在学习如何从windows上的fortran可执行文件调用fortran中的函数。我正在使用gfortran 4.7和photran在eclipse中工作。

我的测试dll在hello.f90中只有一个函数:

hello.f90

代码语言:javascript
复制
subroutine hello
    implicit none
    print *, "Hello World!"
end subroutine hello

使用以下makefile:

代码语言:javascript
复制
all:
    gfortran -Wall -c hello.f90
    gfortran -shared -o hello.dll hello.o

Dependency确认函数"hello_“是导出的。

现在我正在构建一个动态调用它的程序。我根据我在网上找到的示例构建了以下内容,但它没有编译:

main.f90

代码语言:javascript
复制
program main
    implicit none
    integer :: p
    pointer (q, hello)
    p = loadlibrary("hello.dll")
    q = getprocaddress(p, "hello_")
    call hello
end program main

makefile

代码语言:javascript
复制
all:
    gfortran -Wall -pedantic -fcray-pointer main.f90 

错误消息是函数LoadLibrary (和getprocaddress)没有隐式类型。我怀疑这意味着那些函数没有被定义,我需要以某种方式包含它们的头。是那么回事吗?我在c:\mingw\include\winbase.h中为loadlibrary找到了一个声明

干杯,

Marc

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-05 06:55:50

LoadLibrary和GetProcAddress是Windows例程。与任何非内在函数一样,您需要声明这些函数的类型,并且考虑到这些API的性质,您还需要更进一步并提供完整的接口。

如果您正在为32位Windows进行编译,那么这些API使用的是stdcall调用约定。您需要使用gfortran源指令扩展来指定它。

(在64位Windows标准调用中,定义为与C调用约定相同--源指令没有任何效果。)

对于调用约定控件,如果我将DLL代码更改为:

代码语言:javascript
复制
SUBROUTINE hello() BIND(C, NAME='hello')
  IMPLICIT NONE
  PRINT *, 'Hello'
END SUBROUTINE hello

然后,下面的主程序将加载得到的DLL并执行该过程。

代码语言:javascript
复制
PROGRAM Main
  USE, INTRINSIC :: ISO_C_BINDING, ONLY:  &
      C_F_PROCPOINTER, C_FUNPTR, C_INTPTR_T,  &
      C_NULL_CHAR, C_CHAR, C_ASSOCIATED

  IMPLICIT NONE

  INTERFACE 
     FUNCTION LoadLibrary(lpFileName) BIND(C,NAME='LoadLibraryA')
        USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INTPTR_T, C_CHAR
        IMPLICIT NONE 
        CHARACTER(KIND=C_CHAR) :: lpFileName(*) 
        !GCC$ ATTRIBUTES STDCALL :: LoadLibrary 
        INTEGER(C_INTPTR_T) :: LoadLibrary 
     END FUNCTION LoadLibrary 

     FUNCTION GetProcAddress(hModule, lpProcName)  &
         BIND(C, NAME='GetProcAddress')
       USE, INTRINSIC :: ISO_C_BINDING, ONLY:  &
           C_FUNPTR, C_INTPTR_T, C_CHAR
       IMPLICIT NONE
       !GCC$ ATTRIBUTES STDCALL :: GetProcAddress
       TYPE(C_FUNPTR) :: GetProcAddress
       INTEGER(C_INTPTR_T), VALUE :: hModule
       CHARACTER(KIND=C_CHAR) :: lpProcName(*)
     END FUNCTION GetProcAddress      
  END INTERFACE

  ABSTRACT INTERFACE
    SUBROUTINE hello_intf() BIND(C)
      IMPLICIT NONE
    END SUBROUTINE hello_intf
  END INTERFACE

  INTEGER(C_INTPTR_T) :: module_handle
  TYPE(C_FUNPTR) :: proc_address
  PROCEDURE(hello_intf), BIND(C), POINTER :: my_proc

  !****      

  module_handle = LoadLibrary(C_CHAR_'hello.dll' // C_NULL_CHAR)
  IF (module_handle == 0) STOP 'Unable to load DLL'

  proc_address = GetProcAddress( module_handle,  &
      C_CHAR_'hello' // C_NULL_CHAR )
  IF (.NOT. C_ASSOCIATED(proc_address))  &
      STOP 'Unable to obtain procedure address'

  CALL C_F_PROCPOINTER(proc_address, my_proc)

  CALL my_proc

END PROGRAM Main
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14165801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档