简体   繁体   English

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

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

I have written a function in C (for some bitwise operations on 64-bit) and I want to use that function in my excel vba macro. 我已经用C语言编写了一个函数(用于在64位上进行一些按位运算),我想在我的excel vba宏中使用该函数。 I used steps described here to create a DLL file using cygwin (64-bit). 我使用了此处介绍的步骤来使用cygwin(64位)创建DLL文件。

Here are the commands I used to create the actual dll: 这是我用来创建实际dll的命令:

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

The function declaration inside tokenid.c is like this: tokenid.c中的函数声明是这样的:

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

I have tested the dll with a small c program and it works fine. 我已经用小型C程序测试了dll,并且工作正常。 Here's the source code for test.c: 这是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 and test.c (and all other intermediate files) are in the same same directory (cygwin's default). tokenid.c和test.c(以及所有其他中间文件)位于同一目录中(cygwin的默认目录)。

Then I copied the tokenid.dll (cygwin1.dll - dependency walker said it was missing) to the folder where the macro enabled workbook is stored. 然后,我将tokenid.dll(cygwin1.dll-依赖关系行者说它丢失了)复制到启用了宏的工作簿所在的文件夹中。 Here's the test macro I wrote: 这是我编写的测试宏:

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

But excel is unable to find the dll. 但是excel无法找到dll。 Whenever I try to run the macro, I get 每当我尝试运行宏时,我都会

Run-time error 48. File not found 运行时错误48。找不到文件

I have already tried the following: 我已经尝试了以下方法:

  • I tried hardcoding the path but its the same story. 我尝试对路径进行硬编码,但过程相同。
  • I added the path of the current working directory to the system path but to no avail. 我将当前工作目录的路径添加到系统路径,但无济于事。
  • Dependency Walker does not find any missing dll. Dependency Walker找不到任何缺少的dll。 The cygwin1.dll (which it said was missing earlier) is picked up from the current working directory. cygwin1.dll(它说它早些时候丢失了)是从当前工作目录中拾取的。

Can someone point me to the right direction? 有人可以指出我正确的方向吗? What am I doing wrong here? 我在这里做错了什么?

EDIT: I am using Windows 7 (64-bit), Office 2013 and Cygwin 64-bit. 编辑:我正在使用Windows 7(64位),Office 2013和Cygwin 64位。

Also, noticed one weird thing. 另外,注意到一件奇怪的事情。 If I place the dll file in system32 folder and hardcode the path in the code, the error code changes from 48 to 53. The error code is always 48 no matter what else I do. 如果将dll文件放在system32文件夹中,并将路径硬编码在代码中,则错误代码将从48变为53。无论我做什么,该错误代码始终为48。 Not sure why! 不知道为什么!

Solved: 解决了:

I compiled the dll using the following statements: 我使用以下语句编译了dll:

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

I was on 64-bit Windows but Office was still 32-bit. 我使用的是64位Windows,但Office仍然是32位。

I also changed the return type of the declaration in VBA to Currency since I was returning a 64-bit value from the C program. 因为我从C程序返回了64位值,所以我还将VBA中声明的返回类型更改为Currency。

1- you must mark your function as extern to prevent renaming it (if any). 1-您必须将函数标记为extern以防止重命名(如果有)。
2- your function returns long not double . 2-您的函数返回long而不是double
3- no need to put the extension (ie .dll ) in the declaration. 3-无需在声明中放入扩展名(即.dll )。

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

and: 和:

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

this is worked for me (windows 7 32 bit + office 2010 + minGW). 这为我工作(Windows 7 32位+ Office 2010 + minGW)。
if problem still exists, try to run Excel as administrator. 如果问题仍然存在,请尝试以管理员身份运行Excel。
EDIT 编辑
I have got the same error that you had got when I tried Cygwin; 我遇到的错误与尝试Cygwin时遇到的错误相同; after some research I have got the solution: 经过一些研究,我得到了解决方案:
you must use the cross-compiler (from Cygwin) as following: 您必须使用交叉编译器(来自Cygwin),如下所示:
1- for windows 64 bit: 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- for windows 32 bit: 2-对于Windows 32位:

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

As I understood: DLLs built with gcc on Cygwin can only be linked by EXE built with gcc on Cygwin. 据我了解:Cygwin上使用gcc生成的DLL只能通过Cygwin上使用gcc生成的EXE进行链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM