【问题标题】:Why does LoadLibrary fail whilst LoadLibraryA succeeds in loading a DLL? [duplicate]为什么 LoadLibrary 失败,而 LoadLibraryA 成功加载 DLL? [复制]
【发布时间】:2020-01-23 17:54:22
【问题描述】:

我正在尝试将 DLL 加载到 C++ 中,但收到错误代码 126,我认为这意味着找不到 DLL。经过一番摸索,我将LoadLibrary 更改为LoadLibraryA,突然它起作用了。但是,我完全不知道为什么。我意识到我没有提供使该代码可运行的 dll,但如果有人可以解释为什么会发生这种情况,那就太好了?还有一个例子说明如何让LoadLibary 工作。

破解版

#include <stdio.h>
#include <windows.h>

typedef char* (*gf_getCurrentLibraryVersion) ();

int main() {

    gf_getCurrentLibraryVersion getVersion;

    HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
    if (hLib) {
        getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
        printf("Version = %s\n", getVersion());
    }
    else {
        printf("Error loading dll: %d/n", GetLastError());
    }
    printf("Hit any key to continue\n");
    getchar();

    return 0;
}

编译并输出

Error loading dll: 126/nHit any key to continue

到控制台

工作版

#include <stdio.h>
#include <windows.h>

typedef char* (*gf_getCurrentLibraryVersion) ();

int main() {

    gf_getCurrentLibraryVersion getVersion;

    HINSTANCE hLib = LoadLibraryA("libsbnw.dll");
    if (hLib) {
        getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
        printf("Version = %s\n", getVersion());
    }
    else {
        printf("Error loading dll: %d/n", GetLastError());
    }
    printf("Hit any key to continue\n");
    getchar();

    return 0;
}

编译和输出

version is: 1.3.4

【问题讨论】:

  • 您使用什么编译器和标志?你是在定义_UNICODE 等吗?
  • 当你对编译器撒谎时会发生这种情况

标签: c++ winapi dll loadlibrary


【解决方案1】:

您的LoadLibrary((LPCWSTR)"libsbnw.dll") 调用的问题在于您的构建环境将其转换为LoadLibraryW 调用,但是您尝试传递宽字符串的方式是错误的。

正如您所拥有的那样,您只是将 const char* 指针转换为 const wchar_t* 指针,这是行不通的(例如,它将初始 "li" 字符解释为 单个 em> 16 位字符)。

您需要做的是将字符串文字指定为 宽字符 常量,使用 L 前缀:

 HINSTANCE hLib = LoadLibrary(L"libsbnw.dll");

或者,或者,使用TEXT() 宏(当使用UNICODE 构建环境时,这将归结为相同):

 HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));

随时要求进一步解释和/或澄清。

【讨论】:

    【解决方案2】:

    通常编译器会在您犯错时尝试指出。但在这种情况下,您已经告诉它不要通过向字符串添加显式强制转换。

    HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
                               //^^^^^^^^^
    

    我假设您在构建应用时启用了 Unicode,它定义了一个将 LoadLibrary 转换为 LoadLibraryW 的宏。参数必须是宽字符字符串。

    HINSTANCE hLib = LoadLibraryW(L"libsbnw.dll");
    

    当您不确定应用程序是否会使用 Unicode 编译时,您可以使用另一个宏 TEXT() 或更短的形式 _T()。不推荐用于现代代码,因为多年来需要打开或关闭 Unicode 都不是问题,始终使用 Unicode。

    HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
    

    【讨论】:

    • 请注意,现代 Windows 编程的最佳实践是遵循 UTF-8 Everywhere Manifest 并明确调用 Unicode 版本的 Win32 API:LoadLibraryW(L"libsbnw.dll");
    • @ChuckWalbourn 这是一个有趣的观点,但几乎不是“最佳实践”。如果您不使用wchar_t,那么您正在使用 Windows API 并造成很多不必要的摩擦。
    • 这既不是一个有趣的观点,也与 "UTF-8 Everywhere" 运动有关。这只是“最佳实践”。这里的做法是明确的。不要依赖通用文本宏来清理。只需使用匹配的参数类型调用 函数。如果您使用 wchar_t,请调用 API 的 Unicode 变体。现在已经二十年了,我们仍然无法将这一点带回家?
    • 通用文本映射有两个部分:函数名称的转换和参数的转换。你只对后者明确,而不是前者。这是一个错误,正在等待发生。
    • 这是一个错误,无论如何。您是在编译时还是在运行时发现它取决于您用于编译代码的工具。这个问题最初有一个 C++ 和 C 标签。其中一个编译器不会发出诊断。真正重要的一点是你前后不一致。这种不一致后果的严重程度不是您可以控制的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2019-01-20
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多