我一直在寻找有关如何从C ++引用非托管DLL的答案,
Is there a better way to load a dll in C++?
如果没有调用者也有 .LIB 文件,似乎无法在C ++中加载DLL。如果我想在运行时动态加载DLL,如果真的需要.lib文件,如下所示吗?
#include <Windows.h>
HMODULE h;
LPCWSTR l;
DWORD error;
wchar_t *myDLL = L"E:\\...\\myWin32DLL.dll";
l = (LPCWSTR)myDLL;
h = LoadLibrary(l);
error = GetLastError();
如果我使用上面的代码调用LoadLibrary,我得到结果为NULL。 GetLastError()的错误代码是193:ERROR_BAD_EXE_FORMAT。为什么呢?
修改/更新: 我想出了什么是错的 - 我将程序的目标平台(调用DLL)作为x64,一旦我将其更改为Win32,LoadLibrary现在返回非NULL结果。
DLL由一个源文件expFns.cpp组成:
#include <Windows.h>
#define Pi 3.14159
extern _declspec(dllexport)
double circumference(double radius)
{
return 2.0 * radius * Pi;
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
return TRUE;
}
以下是编译方式:
cl expFns.cpp /link /DLL /out:mywin32dll.dll
如果我使用一些众所周知的DLL,例如unrar3.DLL,我仍然会收到错误代码193.为什么我会收到此错误代码?
另一方面,如果我在托管C#中使用P / Invoke,我只需要.DLL的完整路径,不需要.LIB文件,并且DLL的函数调用将起作用。为什么C ++中必须有.LIB文件,但C#不需要.LIB文件?
[DllImport(@"E:\...\myDLL.dll"
, CallingConvention = CallingConvention.Cdecl
, EntryPoint = "get_value")]
internal static extern double get_value(double l, double w, double h);
答案 0 :(得分:5)
只有在您想要静态链接时才需要LIB文件(强制二进制文件和DLL之间存在强依赖关系:如果DLL不存在,则不会加载二进制文件)。 LoadLibrary()
(或LoadLibraryEx()
)绕过所有这些:但另一方面,您必须使用GetProcAddress()(或GetProcAddressEx()
)设置所有入口点的函数指针导出函数的序号或其名称,这可能很麻烦。后者是C#对DllImport
所做的,具有相当友好的语法。
答案 1 :(得分:2)
不,您可以在运行时调用任何DLL上的LoadLibrary和GetProcAddress - 如果您想静态链接DLL(即刚编译完成后),则只需要.LIB。
答案 2 :(得分:2)
.lib仅用于__declspec(dllexport)
,或用于Microsoft的C ++特定DLL导入/导出。 P / Invoke与.DEF文件相同,并使用GetProcAddress,这是C风格的DLL导入/导出。这两者不可互换。