从 .lib 文件创建 DLL
Create a DLL from a .lib file
本题基于以下post:https://whosebug.com/users/9999861/blackbriar
现在我遇到的问题是每次我想使用 dll 时都会出现 System.EntryPointNotFoundException
。异常消息说,在我的 dll 中找不到具有我尝试调用的函数名称的入口点。
这是一个位于 .h 文件中的示例函数:
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall LDL_Init(char* code)
...
#ifdef __cplusplus
}
#endif
然后我像这样在 C# 中导入函数:
[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="LDL_Init", CallingConvention=CallingConvention.StdCall)]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
有人知道我做错了什么吗?
下次尝试:
我用 Dependency Walker 分析了生成的 dll,发现没有导出函数。所以我写了一个包装器-class。这里是新的代码示例:
在Library.h中:
int LDL_Init(char* code);
在LibraryWrapper.h中:
#pragma once
class __declspec(dllexport) LibraryWrapper
{
public:
static int __cdecl LDL_Init(char* code);
};
在LibraryWrapper.cpp.
#include "Library.h"
#include "LibraryWrapper.h"
int LibraryWrapper::LDL_Init(char* code){
return LDL_Init(code);
}
在Library.cs中:
[DllImport("C:\Path\To\Dll\Example.dll")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
可悲的是,我在执行程序时得到了相同的结果:好的旧 System.EntryPointNotFoundException
...
这里是 Dependency Walker 结果的截图:
并且不取消修饰 C++ 方法:
您可以使用 Microsoft DUMPBIN.EXE
工具检查导出:
> dumpbin /EXPORTS Example.dll
Microsoft (R) COFF/PE Dumper Version 14.14.26433.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file Example.dll
File Type: DLL
Section contains the following exports for Example.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
2 0 000110C3 LDL_Init = @ILT+190(LDL_Init)
1 1 00011087 foo = @ILT+130(foo)
Summary
1000 .00cfg
1000 .data
1000 .idata
2000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
8000 .text
10000 .textbss
链接器的任何特殊内容,例如 __declspec(dllexport)
或 #pragma comment(lib, ...)
需要被编译器看到,否则编译器将不知道它们,链接器也不会。对于修改后的头文件,这意味着至少包含一次。
或者,对于模块定义文件 (.def
),它需要添加到项目中(或手动添加 /DEF filename
命令行参数)。
如果可能,使用__cdecl。
__stdcall会在函数名后加@parameter_bytes。
我"solved"在文件Library.cs中进行如下调整的问题:
[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="?LDL_Init@LibraryWrapper@@SAHPEAD@Z")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
字符串 EntryPoint 是基于 Dependency Walker 从我的 dll 中提取的函数名称。之后我遇到了问题,代码的执行停在
行
return LDL_init(code);
在文件中 LibraryWrapper.cpp。通过启用 "native code debugging" 并在调试时按暂停键发现了这一点。
与此同时,我找到了一个由我要控制的设备的生产商提供的.dll。我用 Dependency Walker 分析了 .dll 并插入了入口点。现在可以了。感谢大家的支持。
本题基于以下post:https://whosebug.com/users/9999861/blackbriar
现在我遇到的问题是每次我想使用 dll 时都会出现 System.EntryPointNotFoundException
。异常消息说,在我的 dll 中找不到具有我尝试调用的函数名称的入口点。
这是一个位于 .h 文件中的示例函数:
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall LDL_Init(char* code)
...
#ifdef __cplusplus
}
#endif
然后我像这样在 C# 中导入函数:
[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="LDL_Init", CallingConvention=CallingConvention.StdCall)]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
有人知道我做错了什么吗?
下次尝试:
我用 Dependency Walker 分析了生成的 dll,发现没有导出函数。所以我写了一个包装器-class。这里是新的代码示例:
在Library.h中:
int LDL_Init(char* code);
在LibraryWrapper.h中:
#pragma once
class __declspec(dllexport) LibraryWrapper
{
public:
static int __cdecl LDL_Init(char* code);
};
在LibraryWrapper.cpp.
#include "Library.h"
#include "LibraryWrapper.h"
int LibraryWrapper::LDL_Init(char* code){
return LDL_Init(code);
}
在Library.cs中:
[DllImport("C:\Path\To\Dll\Example.dll")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
可悲的是,我在执行程序时得到了相同的结果:好的旧 System.EntryPointNotFoundException
...
这里是 Dependency Walker 结果的截图:
并且不取消修饰 C++ 方法:
您可以使用 Microsoft DUMPBIN.EXE
工具检查导出:
> dumpbin /EXPORTS Example.dll
Microsoft (R) COFF/PE Dumper Version 14.14.26433.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file Example.dll
File Type: DLL
Section contains the following exports for Example.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
2 0 000110C3 LDL_Init = @ILT+190(LDL_Init)
1 1 00011087 foo = @ILT+130(foo)
Summary
1000 .00cfg
1000 .data
1000 .idata
2000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
8000 .text
10000 .textbss
链接器的任何特殊内容,例如 __declspec(dllexport)
或 #pragma comment(lib, ...)
需要被编译器看到,否则编译器将不知道它们,链接器也不会。对于修改后的头文件,这意味着至少包含一次。
或者,对于模块定义文件 (.def
),它需要添加到项目中(或手动添加 /DEF filename
命令行参数)。
如果可能,使用__cdecl。
__stdcall会在函数名后加@parameter_bytes。
我"solved"在文件Library.cs中进行如下调整的问题:
[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="?LDL_Init@LibraryWrapper@@SAHPEAD@Z")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );
字符串 EntryPoint 是基于 Dependency Walker 从我的 dll 中提取的函数名称。之后我遇到了问题,代码的执行停在
行return LDL_init(code);
在文件中 LibraryWrapper.cpp。通过启用 "native code debugging" 并在调试时按暂停键发现了这一点。
与此同时,我找到了一个由我要控制的设备的生产商提供的.dll。我用 Dependency Walker 分析了 .dll 并插入了入口点。现在可以了。感谢大家的支持。