从 C 源代码编译的 DLL。无法在 excel VBA 中使用。找不到文件错误

DLL compiled from C source code. Not able to use in excel VBA. File not found error

我已经用 C 编写了一个函数(用于 64 位上的一些按位运算),我想在我的 excel vba 宏中使用该函数。 我使用 steps described here 使用 cygwin(64 位)创建 DLL 文件。

以下是我用来创建实际 dll 的命令:

gcc -c tokenid.c
gcc -shared -o tokenid.dll tokenid.o -Wl,--add-stdcall-alias

tokenid.c里面的函数声明是这样的:

extern __declspec(dllexport) unsigned long long __stdcall calculateToken(double epoch_time, LPSTR enb_market[], LPSTR file_type[], long source)

我用一个小的 c 程序测试了 dll,它工作正常。这是 test.c:

的源代码
#include<stdio.h>
#include<windows.h>

//typedef unsigned long long (__stdcall *calcToken)(double, char[], char[], long);
typedef unsigned long long (__stdcall *calcToken)(double, LPSTR, LPSTR, long);

int main(){

  HANDLE ldll;

  calcToken calculateToken = NULL;

  ldll = LoadLibrary("tokenid.dll");
  if(ldll > (void*)HINSTANCE_ERROR){
    FARPROC fptr = GetProcAddress(ldll, "calculateToken");
    calculateToken = (calcToken)(fptr);

    char market[] = {'A','B','C'};
    char usage[] = {'D','E','F'};

    printf("%llu", calculateToken(1431680395, market, usage, 90));
  } else {
    printf("ERROR.");
  }

}

tokenid.c 和 test.c(以及所有其他中间文件)在同一个目录中(cygwin 的默认目录)。

然后我将 tokenid.dll(cygwin1.dll - dependency walker 说它丢失了)复制到存储启用宏的工作簿的文件夹中。这是我写的测试宏:

Option Explicit

Public Declare Function calculateToken Lib "tokenid" (ByVal epoch_time As Double, ByVal market As String, ByVal usageType As String, ByVal source_id As Long) As Currency

Public Sub test()
    '*****************
    'Declare Variables
    '*****************

    Dim market As String, usageType As String
    Dim epoch As Double
    Dim source_id As Long
    Dim tokenid As Currency

        market = "ABC"
        usageType = "DEF" 'file type in the C program
        epoch = 1431680395
        source_id = 90

        tokenid = calculateToken(epoch, market, usageType, source_id)

        Debug.Print tokenid

End Sub

但是excel找不到dll。每当我尝试 运行 宏时,我都会得到

Run-time error 48. File not found

我已经尝试过以下方法:

有人能给我指出正确的方向吗?我在这里做错了什么?

编辑:我正在使用 Windows 7(64 位)、Office 2013 和 Cygwin 64 位。

另外,注意到一件奇怪的事情。如果我将 dll 文件放在 system32 文件夹中并在代码中硬编码路径,则错误代码会从 48 更改为 53。无论我做什么,错误代码始终为 48。不知道为什么!

已解决:

我使用以下语句编译了 dll:

i686-w64-mingw32-gcc -c tokenid.c
i686-w64-mingw32-gcc -shared -o tokenid.dll tokenid.o -Wl,--add-stdcall-alias -static-libgcc

我使用的是 64 位 Windows 但 Office 仍然是 32 位。

我还将 VBA 中声明的 return 类型更改为 Currency,因为我从 C 程序中 returning 了一个 64 位值。

1- 您必须将您的函数标记为 extern 以防止重命名它(如果有的话)。
2- 你的函数 returns long 而不是 double.
3- 无需在声明中添加扩展名(即 .dll)。

extern __declspec(dllexport) unsigned long long __stdcall calculateToken(double epoch_time, LPSTR enb_market[], LPSTR file_type[], long source)
{
    return 10;
}

和:

Public Declare Function calculateToken Lib "tokenid" (ByVal epoch_time As Double, ByVal market As String, ByVal usageType As String, ByVal source_id As Long) As Long

这对我有用(windows 7 32 位 + office 2010 + minGW)。
如果问题仍然存在,请尝试 运行 Excel 作为管理员。
编辑
当我尝试 Cygwin 时,我遇到了同样的错误;经过一些研究,我找到了解决方案:
您必须使用交叉编译器(来自 Cygwin)如下:
1- 对于 windows 64 位:

x86_64-w64-mingw32-gcc -c tokenid.c
x86_64-w64-mingw32-gcc -shared -o tokenid.dll tokenid.o -Wl,--add-stdcall-alias

2- 对于 windows 32 位:

i686-w64-mingw32-gcc -c tokenid.c
i686-w64-mingw32-gcc -shared -o tokenid.dll tokenid.o -Wl,--add-stdcall-alias

据我了解:在 Cygwin 上使用 gcc 构建的 DLL 只能由在 Cygwin 上使用 gcc 构建的 EXE 链接。