【问题标题】:DLL compiled from C source code. Not able to use in excel VBA. File not found error从 C 源代码编译的 DLL。无法在 Excel VBA 中使用。找不到文件错误
【发布时间】:2015-07-27 16:54:51
【问题描述】:

我已经用 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。不知道为什么!

已解决:

我使用以下语句编译了 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 位值。

【问题讨论】:

    标签: c excel vba dll


    【解决方案1】:

    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 位 + 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 链接。

    【讨论】:

    • 感谢您的回答。我进行了更改,但没有成功。另外,我应该提到我正在使用的 windows 和 office 版本。将它们添加到原始帖子中。
    • 也在管理员模式下运行 excel(通过右键单击并选择“以管理员身份运行”打开 excel.exe)但同样的问题。
    • @fonzie :我修改了答案。
    • 谢谢@houssam。有效。我已经用解决它的步骤修改了原始问题。
    • @fonzie :感谢您也提供步骤。
    猜你喜欢
    • 1970-01-01
    • 2012-06-30
    • 2017-10-22
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    相关资源
    最近更新 更多