从 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
我已经尝试过以下方法:
- 我尝试对路径进行硬编码,但还是一样。
- 我把当前工作目录的路径添加到系统路径中,但是没有用。
- 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 中声明的 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 链接。
我已经用 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
我已经尝试过以下方法:
- 我尝试对路径进行硬编码,但还是一样。
- 我把当前工作目录的路径添加到系统路径中,但是没有用。
- 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 中声明的 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 链接。