Reputation: 2937
I want to develop a plugin system using LoadLibrary.
My problem is: I want my function to take a const char*
and LoadLibrary
takes a LPCTSTR
.
I had the bright idea to do (LPCSTR)path
which 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.
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;
}
Upvotes: 10
Views: 15139
Reputation: 942408
Use LoadLibraryA(), it takes a const char*.
Winapi functions that take strings exist in two versions, an A version that takes an Ansi string and a W version that takes a wide string. There's a macro for the function name, like LoadLibrary, that expands to either the A or the W flavor, depending if UNICODE is #defined. You are compiling your program with that #define in effect, so you get LoadLibraryW(). Simply cheat and use LoadLibraryA() explicitly.
Upvotes: 23
Reputation: 490713
The approved method with LoadLibrary
is to not use a char const *
, but instead use a TCHAR const *
, and use the _T
macro on all literals:
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 LoadLibraryW
when _UNICODE
/UNICODE
are defined, and LoadLibraryA
when they're not. Likewise, _T
will give narrow or wide string literals on the same basis, so it all stays in sync.
I generally prefer to use the W
suffixed functions explicitly, and use the L
prefix 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.
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.
Upvotes: 0
Reputation: 308530
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 const
since you're not modifying the string.
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.
Upvotes: 0
Reputation: 29863
I suggest you using TCHAR
and LoadLibrary
instead of using manually char
or wchar_t
and LoadLibraryA
or LoadLibraryW
to make a generic application, both for UNICODE and ASCII characters.
So you could do:
TCHAR x[100] = TEXT("some text");
I suggest you reading this article. LPCTSTR
is a const TCHAR*
.
Why use LoadLibrary
instead of LoadLibraryW
or LoadLibraryA
? To support both UNICODE and ASCII without creating two different programs, one to work with char
and the other with wchar_t
.
Also, take a look at what Microsoft says about it: Conventions for Function Prototypes
Upvotes: 8