エラーは自明です。 char*
ポインターが必要な場合は、wchar_t
バッファー/ポインターを渡しています。それらは互換性のある型ではありません。すべてのエラーメッセージは、A
NSIバージョンのAPI関数が呼び出されていることを示しています。
#undef UNICODE
を使用しないでください! UNICODE
(およびC RTLの場合は_UNICODE
)を定義することは、コードの責任ではありません。コンパイラを呼び出すときは、それを処理するのはプロジェクトの責任です。
手動でUNICODE
を定義しないと、すべてのTCHAR
ベースのWin32 APIマクロ(呼び出し元のものなど)がUnicodeバージョンではなくANSIバージョンにマップされます。
ANSI文字列を使用する場合は、A
NSI関数を明示的に呼び出します。 Unicode文字列を使用する場合は、W
ide関数を明示的に呼び出します。 TCHAR
の定義に依存することをやめてください。
代わりにこれを試してみてください:
NativeLibrary LoadNativeLibraryHelper(const std::string& library_path,
LoadLibraryFunction load_library_api,
NativeLibraryLoadError* error) {
// LoadLibrary() opens the file off disk.
//ThreadRestrictions::AssertIOAllowed();
// Switch the current directory to the library directory as the library
// may have dependencies on DLLs in this directory.
WCHAR current_directory[MAX_PATH] = {0};
bool restore_directory = false;
// THIS IS NOT THE PROPER WAY TO CONVERT A std::string TO A std::wstring!
// This only works properly for ASCII strings. You need to use
// MultiByteToWideChar() or std::wstring_convert or other equivalent
// to convert ANSI data to UNICODE data. Otherwise, library_path should
// be passed as a std::wstring to begin with...
//
std::wstring lp = std::wstring(library_path.begin(), library_path.end());
std::wstring plugin_path, plugin_value;
const wchar_t *res = wcsrchr(lp.c_str(), L'\\');
if (res)
{
plugin_path.assign(lp.c_str(), res);
plugin_value.assign(++res);
if (!plugin_path.empty())
{
GetCurrentDirectoryW(MAX_PATH, current_directory);
restore_directory = SetCurrentDirectoryW(plugin_path.c_str());
}
}
else
plugin_value = lp;
HMODULE module = (*load_library_api)(plugin_value.c_str());
if (!module && error) {
// GetLastError() needs to be called immediately after |load_library_api|.
error->code = GetLastError();
}
if (restore_directory)
SetCurrentDirectoryW(current_directory);
return module;
}
...
NativeLibrary LoadNativeLibraryDynamically(const std::string& library_path) {
LoadLibraryFunction load_library;
load_library = reinterpret_cast<LoadLibraryFunction>(
GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"));
return LoadNativeLibraryHelper(library_path, load_library, NULL);
}
言われていること、依存DLLが検索される場所に影響するSetCurrentDirectory()
を使用しないでください!正しい解決策は、代わりにSetDllDirectory()
(XP SP1 +)またはAddDllDirectory()
(Win8 +)を使用することです。
のみSetDllDirectory()
を使用する:一つは実行時に実際に利用可能な方の使用
NativeLibrary LoadNativeLibraryHelper(const std::string& library_path,
LoadLibraryFunction load_library_api,
NativeLibraryLoadError* error) {
// LoadLibrary() opens the file off disk.
//ThreadRestrictions::AssertIOAllowed();
// Include the library directory as the library may have dependencies on
// DLLs in this directory.
// THIS IS NOT THE PROPER WAY TO CONVERT A std::string TO A std::wstring!
// This only works properly for ASCII strings. You need to use
// MultiByteToWideChar() or std::wstring_convert or other equivalent
// to convert ANSI data to UNICODE data. Otherwise, library_path should
// be passed as a std::wstring to begin with...
//
std::wstring lp = std::wstring(library_path.begin(), library_path.end());
std::wstring plugin_path, plugin_value;
DLL_DIRECTORY_COOKIE cookie = 0;
const wchar_t *res = wcsrchr(lp.c_str(), L'\\');
if (res)
{
plugin_path.assign(lp.c_str(), res);
plugin_value.assign(++res);
if (!plugin_path.empty())
cookie = AddDllDirectory(plugin_path.c_str());
}
else
plugin_value = lp;
HMODULE module = (*load_library_api)(plugin_value.c_str());
if (!module && error) {
// GetLastError() needs to be called immediately after |load_library_api|.
error->code = GetLastError();
}
if (cookie)
RemoveDllDirectory(cookie);
return module;
}
:
NativeLibrary LoadNativeLibraryHelper(const std::string& library_path,
LoadLibraryFunction load_library_api,
NativeLibraryLoadError* error) {
// LoadLibrary() opens the file off disk.
//ThreadRestrictions::AssertIOAllowed();
// Include the library directory as the library may have dependencies on
// DLLs in this directory.
// THIS IS NOT THE PROPER WAY TO CONVERT A std::string TO A std::wstring!
// This only works properly for ASCII strings. You need to use
// MultiByteToWideChar() or std::wstring_convert or other equivalent
// to convert ANSI data to UNICODE data. Otherwise, library_path should
// be passed as a std::wstring to begin with...
//
std::wstring lp = std::wstring(library_path.begin(), library_path.end());
std::wstring plugin_path, plugin_value;
bool restore_old_order = false;
const wchar_t *res = wcsrchr(lp.c_str(), L'\\');
if (res)
{
plugin_path.assign(lp.c_str(), res);
plugin_value.assign(++res);
if (!plugin_path.empty())
restore_old_order = SetDllDirectoryW(plugin_path.c_str());
}
else
plugin_value = lp;
HMODULE module = (*load_library_api)(plugin_value.c_str());
if (!module && error) {
// GetLastError() needs to be called immediately after |load_library_api|.
error->code = GetLastError();
}
if (restore_old_order)
SetDllDirectoryW(NULL);
return module;
}
はAddDllDirectory()
のみを使用
NativeLibrary LoadNativeLibraryHelper(const std::string& library_path,
LoadLibraryFunction load_library_api,
NativeLibraryLoadError* error) {
// LoadLibrary() opens the file off disk.
//ThreadRestrictions::AssertIOAllowed();
// Include the library directory as the library may have dependencies on
// DLLs in this directory.
typedef BOOL (WINAPI* SetDllDirectoryFunction)(LPCWSTR lpPathName);
typedef PVOID DLL_DIRECTORY_COOKIE;
typedef DLL_DIRECTORY_COOKIE (WINAPI* AddDllDirectoryFunction)(PCWSTR NewDirectory);
typedef BOOL(WINAPI* RemoveDllDirectoryFunction)(DLL_DIRECTORY_COOKIE Cookie);
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
AddDllDirectoryFunction add_dll_directory;
add_dll_directory = reinterpret_cast<AddDllDirectoryFunction>(
GetProcAddress(hKernel32, "AddDllDirectory"));
RemoveDllDirectoryFunction remove_dll_directory;
if (add_dll_directory)
{
remove_dll_directory = reinterpret_cast<RemoveDllDirectoryFunction>(
GetProcAddress(hKernel32, "RemoveDllDirectory"));
}
else
remove_dll_directory = NULL;
SetDllDirectoryFunction set_dll_directory;
if (!(add_dll_directory && remove_dll_directory))
{
set_dll_directory = reinterpret_cast<SetDllDirectoryFunction>(
GetProcAddress(hKernel32, "SetDllDirectoryW"));
}
else
set_dll_directory = NULL;
// THIS IS NOT THE PROPER WAY TO CONVERT A std::string TO A std::wstring!
// This only works properly for ASCII strings. You need to use
// MultiByteToWideChar() or std::wstring_convert or other equivalent
// to convert ANSI data to UNICODE data. Otherwise, library_path should
// be passed as a std::wstring to begin with...
//
std::wstring lp = std::wstring(library_path.begin(), library_path.end());
DLL_DIRECTORY_COOKIE cookie = 0;
bool restore_old_order = false;
std::wstring current_directory;
std::wstring plugin_path, plugin_value;
const wchar_t *res = wcsrchr(lp.c_str(), L'\\');
if (res)
{
plugin_path.assign(lp.c_str(), res);
plugin_value.assign(++res);
if (!plugin_path.empty())
{
if (add_dll_directory && remove_dll_directory)
cookie = (*add_dll_directory)(plugin_path.c_str());
else if (set_dll_directory)
restore_old_order = (*set_dll_directory)(plugin_path.c_str());
else
{
current_directory.resize(MAX_PATH);
GetCurrentDirectoryW(MAX_PATH, ¤t_directory[0]);
if (!SetCurrentDirectoryW(plugin_path.c_str()))
current_directory.clear();
}
}
}
else
plugin_value = lp;
HMODULE module = (*load_library_api)(plugin_value.c_str());
if (!module && error) {
// GetLastError() needs to be called immediately after |load_library_api|.
error->code = GetLastError();
}
if (remove_dll_directory)
{
if (cookie)
(*remove_dll_directory)(cookie);
}
else if (set_dll_directory)
{
if (restore_old_order)
(*set_dll_directory)(NULL);
}
else if (!current_directory.empty())
SetCurrentDirectoryW(current_directory.c_str());
return module;
}
GetCurrentDirectoryの 'の第2引数()' 'LPSTR'とされていますが、' current_directory'は 'wchar_t '。 – Barmar
なぜあなたは '#undef UNICODE'を持っていますか?これは、Windows APIの 'wstring'に正しい関数呼び出しを使用するために必要です。 – 1201ProgramAlarm
間違っているのは、引数2を 'wchar_t [260]'から 'LPSTR'に変換できず、引数1を 'wchar_t *'から 'LPCSTR'に変換できないということです。さらに、引数1を 'wchar_t [260]'から 'LPCSTR'に変換することはできません。最後に、引数1を 'const wchar_t [13]'から 'LPCSTR'に変換することはできません。 –