'hmodule loadlibrarya (lpcstr)': невозможно преобразовать аргумент 1 из 'const _elem *' в 'lpcstr'

в vC++ у меня есть решение с двумя проектами. В проекте A есть dllLoader.h и dllLoader.cpp, которые загружают dll с LoadLibrary, и мне нужно вызвать его функции в проекте B. Поэтому я скопировал и вставил файл заголовка и cpp в проект B.

Project A Main.cpp
------------------
#include "../Plugin/DllLoader.h"
#include "../Plugin/Types.h"
int main(){
std::string str("plugin.dll");
bool scuccessfulLoad = LoadDll(str);}

и вот dllLoader в Project A (зеркало / копия в Project B меняются с изменениями здесь)

bool LoadDll(std::string FileName)
{
    std::wstring wFileName = std::wstring(FileName.begin(), FileName.end());
    HMODULE dllHandle1 = LoadLibrary(wFileName.c_str());
    if (dllHandle1 != NULL)
    { ****   
      return TRUE;
    }

Само построение проекта не показывает никаких ошибок и выполняется успешно, но когда я создаю Решение (которое содержит другие проекты), я получаю сообщение об ошибке

C2664 'HMODULE LoadLibraryA(LPCSTR)': cannot convert argument 1 from 'const _Elem *' to 'LPCSTR'

Почему бы вам напрямую не вызвать LoadLibrary ("plugin.dll")? Вы передаете широкую строку функции, которая запрашивает строку.

zdf 26.10.2018 08:45

@ZDF Конечно, это не сработает для проектов, в которых определен UNICODE .....

David Heffernan 26.10.2018 08:48

В этом случае правильным вызовом будет LoadLibrary (TEXT ("plugin.dll")). Или _T.

zdf 26.10.2018 08:49

@ZDF Я так не думаю. Этот код выглядит так, как будто он написан для целевого Unicode. Если вы не поддерживаете Win 9x, вам не следует использовать TCHAR.

David Heffernan 26.10.2018 08:51

@DavidHeffernan Настройки проекта разные.

zdf 26.10.2018 08:52

@ZDF да это было у меня плохо, некорректно отследил ошибку. Отредактировал вопрос

Amir-Mousavi 26.10.2018 08:58

@ZDF Действительно. Таков мой ответ.

David Heffernan 26.10.2018 09:36
std::wstring wFileName = std::wstring(FileName.begin(), FileName.end()); - это ошибка. Я не знаю, почему постоянно появляется это «преобразование», но оно ничего не преобразовывает. Он уничтожает данные. Если исходная строка не закодирована строго ASCII, это не удастся. Это будет особенно неудачно, если исходная строка закодирована в UTF-8. Мы не знаем, какую кодировку ожидает ваш интерфейс, поэтому мы мало что можем сделать, чтобы предложить решение.
IInspectable 26.10.2018 10:30
1
8
2 218
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы передаете функции широкую строку. Таким образом, код явно предназначен для компиляции с ориентацией на UNICODE, так что макрос LoadLibrary расширяется до LoadLibraryW. Но проект, в котором произошел сбой кода, не предназначен для UNICODE. Следовательно, макрос здесь расширяется до LoadLibraryA. И, следовательно, ошибка компилятора, потому что вы передаете широкую строку.

Таким образом, проблема в том, что у вас несовместимые настройки компилятора в разных проектах. Просмотрите конфигурацию проекта сбойного, чтобы убедиться, что определены согласованные условные выражения. То есть убедитесь, что необходимые условные выражения (предположительно для включения UNICODE) определены во всех проектах, содержащих этот код.

Да, вы правы, столбец ошибок проекта пропал, теперь я увидел, что ошибка связана с скопированной версией файла. Отредактировал вопрос

Amir-Mousavi 26.10.2018 08:57

@ Амир-Мусави, ты пробовал HMODULE dllHandle1 = LoadLibrary(L"plugin.dll");? Это работает?

Jabberwocky 26.10.2018 09:31

@ Amir-Mousavi Я совершенно уверен, что мой ответ объясняет ошибку. Код написан в предположении, что LoadLibrary расширяется до LoadLibraryW, но в неудачном проекте он расширяется до LoadLibraryA.

David Heffernan 26.10.2018 09:35

@Jabberwocky да, пробовал, в скопированной версии загрузчика написано: const wchat_t* несовместим с LPCSTR

Amir-Mousavi 26.10.2018 10:11

@ Amir-Mousavi, затем попробуйте HMODULE dllHandle1 = LoadLibrary("plugin.dll"); или HMODULE dllHandle1 = LoadLibraryW(L"plugin.dll");

Jabberwocky 26.10.2018 10:12

@ Амир-Мусави Конечно, есть. Это потому, что LoadLibrary расширяется до LoadLibraryA в неудачном проекте, а L"plugin.dll" - это широкая строка. Вы знаете разницу между LoadLibraryA и LoadLibraryW?

David Heffernan 26.10.2018 10:13

@Jabberwocky Ты, кажется, тоже этого не понимаешь. Есть несколько проектов. Некоторые скомпилированы для UNICODE, некоторые нет.

David Heffernan 26.10.2018 10:13

@Jabberwocky LoadLibrary("plugin.dll"); работает в копии, но в оригинале говорит: const cahr* несовместим с LPCWSTR, LoadLibrary(L"plugin.dll"); работает в оригинале, но в копии говорит: const wchat_t* несовместим с LPCSTR

Amir-Mousavi 26.10.2018 10:16

@DavidHeffernan Спасибо, ваш ответ нацелен на проблему, но как мне ее решить? Проект A использует соглашение __stdcall, проект B использует __cdecl

Amir-Mousavi 26.10.2018 10:19

@ Амир-Мусави Дай мне попробовать в последний раз. Вместо того, чтобы пробовать что-то наугад, не понимая, я считаю, что путь к решению этой проблемы - это понимание. Вы знаете разницу между LoadLibraryA и LoadLibraryW?

David Heffernan 26.10.2018 10:21

@DavidHeffernan ну, я бы сказал, что не совсем :(

Amir-Mousavi 26.10.2018 10:23

Тогда вам нужно сделать это вашей следующей задачей. Как только вы поймете разницу и как условия определяют, будет ли LoadLibrary расширяться до LoadLibraryA или LoadLibraryW, вы сможете решить проблему. Пока вы этого не поймете, я убежден, что вы просто зря теряете время.

David Heffernan 26.10.2018 10:24

@ Amir-Mousavi при передаче строковый литерал в функцию API с поддержкой TCHAR (например, LoadLibrary()) используйте макрос TEXT(), чтобы код компилировался как в ANSI, так и в UNICODE: LoadLibrary(TEXT("plugin.dll")); или LPCTSTR FileName = TEXT("plugin.dll"); LoadLibrary(FileName);. При передаче данные времени выполнения вместо этого пропустите функцию на основе TCHAR и напрямую вызовите соответствующую версию, которая соответствует используемому типу символа: char *FileName = ...; LoadLibraryA(FileName);wchar_t *FileName = ...; LoadLibraryW(FileName); (вместо этого вы можете использовать std::string и std::wstring, если хотите)

Remy Lebeau 26.10.2018 19:53
Ответ принят как подходящий

Ваша функция LoadDll() принимает std::string в качестве входных данных, преобразует его (неправильный путь 1) в std::wstring, а затем передает его в LoadLibrary(). Однако LoadLibrary() не является реальной функцией, это макрос препроцессора, который расширяется до LoadLibraryA() или LoadLibraryW() в зависимости от того, настроен ли ваш проект на отображение TCHAR в char для ANSI или wchar_t для UNICODE:

WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryA(
    __in LPCSTR lpLibFileName
    );
WINBASEAPI
__out_opt
HMODULE
WINAPI
LoadLibraryW(
    __in LPCWSTR lpLibFileName
    );
#ifdef UNICODE
#define LoadLibrary  LoadLibraryW
#else
#define LoadLibrary  LoadLibraryA
#endif // !UNICODE

В вашей ситуации проект, который не может быть скомпилирован, настроен для ANSI, поэтому возникает ошибка компилятора, потому что вы передаете const wchar_t* в LoadLibraryA(), где вместо этого ожидается const char*.

Самое простое решение - полностью избавиться от преобразования и напрямую вызвать LoadLibraryA():

bool LoadDll(std::string FileName)
{
    HMODULE dllHandle1 = LoadLibraryA(FileName.c_str());
    ...
}

Если вы все еще хотите преобразовать std::string в std::wstring1, вам следует вместо этого напрямую вызвать LoadLibraryW():

bool LoadDll(std::string FileName)
{
    std::wstring wFileName = ...;
    HMODULE dllHandle1 = LoadLibraryW(wFileName.c_str());
    ...
}

Таким образом, ваш код всегда соответствует вашим данным и не зависит от какой-либо конкретной конфигурации проекта.

1: the correct way to convert a std::string to a std::wstring is to use a proper data conversion method, such as the Win32 MultiByteToWideChar() function, C++11's std::wstring_convert class, a 3rd party Unicode library, etc. Passing std::string iterators to std::wstring's constructor DOES NOT perform any conversions, it simply expands the char values as-is to wchar_t, thus any non-ASCIIchar values > 0x7F will NOT be converted to Unicode correctly (UTF-16 is Windows's native encoding for wchar_t strings). Only the 7-bit ASCII characters (0x00 - 0x7F) are the same values in ASCII, ANSI codepages, Unicode UTF encodings, etc. Higher-valued characters require conversion.

Это действительно должно читать "любые символы, отличные от ASCII". Режим отказа не ограничивается кодировкой ANSI. Он также не сработает для любой кодовой точки, не закодированной в ASCII UTF-8.

IInspectable 26.10.2018 22:08

Спасибо, это лучшее описание и понимание различий типов.

Amir-Mousavi 28.10.2018 13:55

Другие вопросы по теме