2

我正在为 Windows 64 使用 gfortran 编译器(在 Simply Fortran 下),在创建基本的 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 而此文件位于声明中提到的正确文件中,如果有人可以帮忙,请!

先感谢您

4

4 回答 4

0

我也遇到过同样的问题,一直困扰着我,直到找到解决方案。如果您查看依赖walker,则缺少引用的dll,很可能来自调试环境。我的是DFORTD.DLL

解决方案是

  1. 编译为发行版并确保所有依赖的 dll 都可用
  2. 或使用静态库参数编译/libs:static或为我在设置中指定Fortran/Library/Debug Single-threaded

最后,确保您的 dll 中没有缺少依赖项

要看

于 2014-09-16T18:41:31.323 回答
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下做同样的事情会如此复杂:(

于 2013-08-06T20:01:17.183 回答
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

于 2013-08-06T10:20:01.017 回答
0

我已经成功地从一个玩具 DLL 函数填充了一个Longs 的二维数组,使用以下方法从 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  

编译时特别注意-mrtdand的使用。-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。

我很感谢这里的作者,因为我最初指出了一个可行的解决方案。这个comp.lang.fortran 线程中也出现了一个非常相似的解决方案。

于 2016-11-14T17:30:53.507 回答