windows LoadLibrary 采用 LPCTSTR

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5208415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:21:00  来源:igfitidea点击:

LoadLibrary taking a LPCTSTR

c++windowsdllloadlibrary

提问by Ben

I want to develop a plugin system using LoadLibrary.
My problem is: I want my function to take a const char*and LoadLibrarytakes a LPCTSTR.
I had the brightidea to do (LPCSTR)pathwhich kept giving me a module not found error.

Current code is below. If I uncomment the widepath = L..line it works fine. I've read solutions using MFC but I'd like to not use MFC.

我想使用 LoadLibrary 开发一个插件系统。
我的问题是:我希望我的函数采用 aconst char*LoadLibrary采用LPCTSTR.
我有明亮的想法做(LPCSTR)path这不停地给我找不到错误的模块。

当前代码如下。如果我取消注释该widepath = L..行,它就可以正常工作。我已经阅读了使用 MFC 的解决方案,但我不想使用 MFC。

Current code:

当前代码:

bool PluginLoader::Load(char *path)
{
    path = "Release\ExamplePlugin.dll";
    LPCTSTR widepath = (LPCTSTR)path;
    //widepath = L"Release\ExamplePlugin.dll";

    HMODULE handle = LoadLibrary(widepath);
    if (handle == 0)
    {
        printf("Path: %s\n",widepath );
        printf("Error code: %d\n", GetLastError());

        return false;
    }

    int (*load_callback)() = (int (*)()) GetProcAddress(handle, "_plugin_start@0");

    if (load_callback == 0)
    {
        return false;
    }

    return load_callback() == LOAD_SUCCESS;
}

回答by Hans Passant

Use LoadLibraryA(), it takes a const char*.

使用 LoadLibraryA(),它需要一个 const char*。

Winapi functions that take strings exist in two versions, an A version that takes a Ansi strings and a W version that takes wide strings. There's a macro for the function name, like LoadLibrary, that expands to either the A or the W, depending if UNICODE is #defined. You are compiling your program with that #define in effect, so you get LoadLibraryW(). Simply cheat and use LoadLibraryA().

接受字符串的 Winapi 函数有两个版本,一个是接受 Ansi 字符串的 A 版本,另一个是接受宽字符串的 W 版本。函数名称有一个宏,如 LoadLibrary,它扩展为 A 或 W,具体取决于 UNICODE 是否为 #defined。您正在使用有效的#define 编译您的程序,因此您将获得 LoadLibraryW()。只需作弊并使用 LoadLibraryA()。

回答by Oscar Mederos

I suggest you using TCHARand LoadLibraryinstead of using manually charor wchar_tand LoadLibraryAor LoadLibraryWto make a generic application, both for UNICODEand ASCIIcharacters.

我建议您使用TCHARandLoadLibrary而不是手动使用charorwchar_tLoadLibraryAorLoadLibraryW来制作通用应用程序,包括UNICODEASCII字符。

So you could do:

所以你可以这样做:

TCHAR x[100] = TEXT("some text");

TCHAR x[100] = TEXT("some text");

I suggest you reading this article. LPCTSTRis a const TCHAR*.

我建议你阅读这篇文章LPCTSTR是一个const TCHAR*

Why use LoadLibraryinstead of LoadLibraryWor LoadLibraryA? To support both UNICODEand ASCIIwithout creating two different programs, one to work with charand the other with wchar_t.

为什么使用LoadLibrary代替LoadLibraryWLoadLibraryA?要同时支持UNICODEASCII而无需创建两个不同的程序,一个char使用wchar_t.

Also, take a look at what Microsoft says about it: Conventions for Function Prototypes

另外,看看微软是怎么说的:Conventions for Function Prototypes

回答by Mark Ransom

If you continue to use a char *for the parameter, you'll run into cases where an unusual character is used in the filename and the LoadLibrary will fail. Change the function to use wchar_t instead, and while you're at it make the parameter constsince you're not modifying the string.

如果您继续使用 achar *作为参数,您将遇到在文件名中使用异常字符并且 LoadLibrary 将失败的情况。将函数更改为使用 wchar_t ,并且当您使用它时,请创建参数,const因为您没有修改字符串。

bool PluginLoader::Load(const wchar_t *path)

I think you'll find that LPCTSTR on 32-bit Windows is a macro that expands to const wchar_t *when the program options are set to Unicode.

我想您会发现 32 位 Windows 上的 LPCTSTR 是一个宏,const wchar_t *当程序选项设置为 Unicode 时,它会扩展到。

回答by Jerry Coffin

The approved method with LoadLibraryis to notuse a char const *, but instead use a TCHAR const *, and use the _Tmacro on all literals:

批准的方法 withLoadLibrary使用 a char const *,而是使用 a TCHAR const *,并_T在所有文字上使用宏:

bool PluginLoader::Load(TCHAR const *path) {

    path = _T("Release\ExamplePlugin.dll");

    HMODULE handle = LoadLibrary(path);
    if (handle == 0)
    {
        _tprintf(_T("Path: %s\n"),widepath );
        _tprintf(_T("Error code: %d\n"), GetLastError());

        return false;
    }

    int (*load_callback)() = (int (*)()) GetProcAddress(handle, _T("_plugin_start@0"));

    if (load_callback == 0)
    {    
        return false;
    }    
    return load_callback() == LOAD_SUCCESS;
}

This will automatically use LoadLibraryWwhen _UNICODE/UNICODEare defined, and LoadLibraryAwhen they're not. Likewise, _Twill give narrow or wide string literals on the same basis, so it all stays in sync.

这将LoadLibraryW_UNICODE/UNICODE被定义时自动使用,LoadLibraryA当它们没有被定义时。同样,_T将在相同的基础上给出窄或宽的字符串文字,因此它们都保持同步。

I generallyprefer to use the Wsuffixed functions explicitly, and use the Lprefix on string literals. Windows works almost exclusively with wide strings internally anyway, so the version A-suffixed versions that take narrow string literals are mostly small stubs that convert their arguments to wide strings, then call the wide string version. Using the wide string version directly saves both time and memory.

通常更喜欢W显式使用后缀函数,并L在字符串文字上使用前缀。无论如何,Windows 在内部几乎只使用宽字符串,因此A采用窄字符串文字的版本后缀版本大多是将其参数转换为宽字符串的小存根,然后调用宽字符串版本。直接使用宽字符串版本既节省时间又节省内存。

Narrow string support in Windows was originally there primarily for compatibility with the long-since defunct Windows 95/98/SE/Me line that lacked wide string support. Those have been gone for quite a while, so about the only reason to use narrow literals now is because that's what you're being supplied from some outside source.

Windows 中的窄字符串支持最初主要是为了与缺乏宽字符串支持的早已不复存在的 Windows 95/98/SE/Me 系列兼容。那些已经消失了很长一段时间,所以现在使用窄文字的唯一原因是因为这是从某些外部来源提供的。