我正在使用gfortran编译器(在Simply Fortran下)用于Windows 64,当创建一个基本的fortran dll进行测试时,我无法在VBA下运行它,然后得到运行时错误48:找不到dll。
这是我的fortran子程序代码:
subroutine multiply(x, y, z)
!DEC$ ATTRIBUTES DLLEXPORT :: multiply
!DEC$ ATTRIBUTES ALIAS : "multiply" :: multiply
real, intent(in):: x, y
real, intent(out):: z
z = x * y
end subroutine multiply
我创建了一个类型库:gfortran -shared -omultiply.dll multiply.f90 该库位于“C:\ Users \ Olivier \ Documents \ Fortran \”
中和我的VBA代码(我正在使用VBA 7.0):
Declare Sub multiply Lib "C:\Users\Olivier\Documents\Fortran\multiply.dll" (x As Single, y As Single, ByRef z As Single)
Sub test()
Dim x As Single
Dim y As Single
Dim z As Single
x = 2
y = 3
Call multiply(x, y, z)
Cells(1, 1) = z
End Sub
运行此VBA代码时,它表示无法找到multiply.dll,而此文件位于声明中提到的正确文件中,如果有人可以提供帮助的话!
提前谢谢
答案 0 :(得分:0)
您是否尝试使用LoadLibrary-API?
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _
ByVal lpLibFileName As String) As Long
Declare Sub multiply Lib "multiply.dll" ( _
x As Single, _
y As Single, _
ByRef z As Single)
'Call LoadLibrary ONCE!!!! before calling 'multiply', e.g. on opening the workbook
LoadLibrary "C:\Users\Olivier\Documents\Fortran\multiply.dll"
此致
AKDA
答案 1 :(得分:0)
我的Excel 2010确实是32位版本,因此我构建了32位DLL与STDCALL
相乘:
subroutine multiply(x, y, z)
!GCC$ ATTRIBUTES STDCALL :: multiply
real , intent (in) :: x, y
real , intent (inout) :: z
z = x * y
end subroutine multiply
当我用Dependency Walker打开这个DLL时,它说找不到LIBGCC_S_SJLJ-1.DLL
,我不知道如何使用ALIAS解决这个问题,当在VBA下运行时我现在得到运行时错误53,如果有人请可能会有所帮助,这远远超出了我的能力,在R下连接fortran dll是如此容易,我无法想象在VBA下做同样的事情是如此复杂:(
答案 2 :(得分:0)
我遇到了同样的问题,直到找到解决方案才困扰我。如果查看依赖性walker,则缺少引用的dll,很可能来自调试环境。我是DFORTD.DLL
。
解决方案是
/libs:static
参数进行编译,或者在设置Fortran/Library/Debug Single-threaded
中指定。最后,请确保您的dll中没有遗漏的依赖项
答案 3 :(得分:0)
我已成功从玩具DLL函数填充Long
的2D数组,使用以下方法从Excel VBA调用。
Fortran代码:
Subroutine FortranDLL(Array1, dim1, dim2)
Implicit None
Integer :: dim1, dim2
Integer :: Array1(1:dim1, 1:dim2)
Integer :: i, j
do i=1,dim1
do j=1,dim2
Array1(i,j)=(10*i) + j
end do
end do
End Subroutine FortranDLL
使用Code :: Blocks编译:
mingw32-gfortran.exe -Jobj\Release\ -mrtd -fno-underscoring -Wall -DBUILD_DLL -O2 -c D:\Test2\main.f95 -o obj\Release\main.o
mingw32-gfortran.exe -shared -Wl,--output-def=bin\Release\libTest2.def -Wl,--out-implib=bin\Release\libTest2.a -Wl,--dll obj\Release\main.o -o bin\Release\Test2.dll -s
特别注意编译时使用-mrtd
和-fno-underscoring
。
然后是Excel VBA:
Option Explicit
Option Base 1
Declare Sub fortrandll Lib "D:\Test2\bin\Release\Test2.dll" _
(ByRef Array1 As Long, ByRef rows As Long, ByRef cols As Long)
Sub TestDLL()
Const rows As Long = 7
Const cols As Long = 5
Dim Arr(1 To rows, 1 To cols) As Long
Call fortrandll(Arr(1, 1), rows, cols)
ActiveSheet.Range("A1").Resize(rows, cols).Value = Arr
End Sub
请注意,数组的第一个元素作为普通的Long传递给DLL ByRef。
我非常感谢作者here,感谢我对工作解决方案的初步建议。一个非常类似的解决方案也出现在this comp.lang.fortran线程中。