首页 文章

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

提问于
浏览
2

我在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 - 依赖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 . 每当我尝试运行宏时,我都会得到

运行时错误48.找不到文件

我已经尝试过以下方法:

  • 我试过硬编码路径,但它的故事是一样的 .

  • 我将当前工作目录的路径添加到系统路径但无济于事 .

  • Dependency Walker没有找到任何丢失的dll . 从当前的工作目录中选取了cygwin1.dll(它说之前没有丢失) .

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

编辑:我使用的是Windows 7(64位),Office 2013和Cygwin 64位 .

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

Solved:

我使用以下语句编译了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中声明的返回类型更改为Currency,因为我从C程序返回64位值 .

1 回答

  • 0

    1-您必须将您的功能标记为 extern 以防止重命名(如果有) .
    2-你的函数返回 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位办公室2010 minGW) .
    如果问题仍然存在,请尝试以管理员身份运行Excel .
    EDIT
    我遇到了与我尝试Cygwin时相同的错误;经过一番研究,我得到了解决方案:
    你必须使用交叉编译器(来自Cygwin),如下所示:
    1- for windows 64 bit:

    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进行链接 .

相关问题