是否.LIB文件需要在C ++中调用DLL而不是C#P / Invoke?

时间:2011-04-24 16:43:44

标签: c++ visual-c++ dll dllimport loadlibrary

我一直在寻找有关如何从C ++引用非托管DLL的答案,

Is there a better way to load a dll in C++?

DLL References in Visual 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);

3 个答案:

答案 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导入/导出。这两者不可互换。