我想在windows中使用gfortran (mingw - 64位)编译和链接一个动态链接库(dll)。我在Excel 64位中测试生成的dll。我注意到,Excel不返回任何结果(它返回:#VALUE!)以下Fortran代码:
Function RANDGF() bind(c)
use ISO_C_BINDING
implicit none
!GCC$ ATTRIBUTES DLLEXPORT :: RANDGF
Double Precision :: RANDGF
Double Precision :: A
Call RANDOM_NUMBER(A)
RANDGF = 2.0
END
但是,如果我注释Call RANDOM_NUMBER(A)
行,DLL将返回预期的结果。我用于编译的命令是:
gfortran -shared -fpic -o randgf.dll randgf.f90
这是我的VBA代码在Excel:
Private Declare PtrSafe Function randgf Lib "randgf.dll" () As Double
Public Function gfort_res() As Double
gfort_res = randgf()
End Function
如果我想在DLL中使用它们,我应该怎么做才能在代码中调用像RANDOM_NUMBER
这样的函数?
有两个主要问题导致Excel不执行函数:
其中之一,就是Excel找不到DLL文件,这是因为,即使dll文件是在同一文件夹的excel工作表,excel的进程当前目录不相同
对于这个问题,有两种可能的解决方案:
第一个:在函数声明中,您可以将DLL文件的完整路径:
Private Declare PtrSafe Function randgf Lib "C:myexcellibrandfuncrandgf.dll" () As Double
第二个:在调用函数之前,您可以将当前目录更改为dll文件夹:
Private Declare PtrSafe Function randgf Lib "randgf.dll" () As Double
Public Function gfort_res() As Double
ChDrive "C"
ChDir "myexcellibrandfunc"
gfort_res = randgf()
End Function
第二个问题是Excel无法在DLL文件中找到函数。
对于这个问题,也有两种可能的解决方案:
第一个:可以用"别名"来表示函数的序数。在申报时子句(例如序数为1):
Private Declare PtrSafe Function RANDFG Lib "randfg.dll" Alias "#1" () As Double
秒:如果您使用的是fortran 2003或更高版本,您可以指定绑定名称这将出口:
function RANDGF() bind(c, name="RANDGF")
use ISO_C_BINDING
implicit none
!GCC$ ATTRIBUTES DLLEXPORT :: RANDGF
Double Precision :: RANDGF
Double Precision :: A
call RANDOM_NUMBER(A)
end function RANDGF
重要的:所有的VBA代码应该在一个模块内,否则它将无法工作。
我找到了这种行为的原因。在运行我的DLL之前,我必须将gfortran库复制到我的目标计算机。我只是将所有lib*.dll文件从mingw64bin目录复制到目标计算机的windowssystem32文件夹,现在dll工作正常,Excel返回所需的结果。
是否有任何方法自动加载所需的DLL从mingw64bin到我自己的DLL (randg . DLL)在编译和链接在我的源计算机?我想避免从mingw64bin中复制所有lib*.dll文件。