В настоящее время у меня есть образец C++, вызывающий функцию C++ DLL следующим образом:
typedef BOOL(__stdcall *f_funci)(const char*, char*);
HINSTANCE hGetProcIDDLL = LoadLibrary(L"myDLL.dll");
f_funci DoSmth= (f_funci)GetProcAddress(hGetProcIDDLL, "function");
std::string test = "The cake is a lie, it's actually a Brownie...";
char *out = new char[124];
DoSmth(&test[0], out);
И прототип функции DLL:
BOOL function(const char *in, char *out){}
Проблема в том, что когда я вызываю эту функцию DLL, я получаю совершенно случайный результат на in[x] (независимо от значения x) (с использованием отладчика Visual Studio).
Однако, если я просто вставлю эту функцию в свой .cpp, in[x] всегда будет тем результатом, которого я ожидал бы получить.
Что я проверил:
Я думаю, что это могло произойти, но не знаю достаточно, чтобы гарантировать ответ Да / Нет:
Пожалуйста, подумайте о том, чтобы узнать подробности, если что-то неясно.
@ ap-osd: Вы просили дать разъяснения в своем комментарии, этого должно было быть достаточно; Я пометил ваш ответ (который на самом деле просто повторяет вышеуказанный вопрос) для удаления. Тем более, что передача результата c_str() / data() функции, принимающей строку C (const char *), очень четко определена; эта часть вашего «ответа» неверна - и даже если она не так четко определена, даже передача &test[0]должен не будет проблемой.
@DevSolar - Я просто хотел подчеркнуть тот факт, что внутренняя память std::string может изменяться, и ее ненадежно удерживать. См. Ссылки cplusplus.com/reference/string/string/c_str и en.cppreference.com/w/cpp/string/basic_string/c_str. В любом случае я ограничусь ответом на конкретную проблему.
@ ap-osd: Это не более или менее ненадежно, чем прямая передача const char *. Если вы смотрите на однопоточный, он безопасен для является, если вы смотрите на многопоточность, он безопасен, если вы не начинаете изменять строковый объект (точно так же, как вы могли бы изменять строковый объект C, например, освобождая или повторно выделяя его память). Это отвлекающий маневр.
@DevSolar - Теоретически это справедливо. Но у меня были аналогичные проблемы с передачей std::string через библиотеки DLL. Может быть, вы лучше объясните, почему это происходит, и я с радостью удалю свой «неправильный» ответ.
@ ap-osd: передача std::string через границы DLL может быть проблематичной из-за различий в представлении объектов. Но OP - это нет, передающий std::string, но const char *, который только в этом случае находится в настоящее время под контрольstd::string. Здесь нечего смотреть...
Исправление ... здесь нечего видеть, если OP прошел через c_str() / data(), что было бы правильным способом сделать это - хотя я не могу сейчас придумать, что соответствующая реализация не могла бы работать и с &test[0].
Если функция действительно прототипирована как BOOL function(const char *in, char *out), то соглашение о вызовах не указано, поэтому она, скорее всего, использует __cdecl, а не __stdcall, как вы утверждаете. Если ваш компилятор не настроен на использование __stdcall в качестве соглашения о вызовах по умолчанию. Хотя это применимо только к 32-битной сборке, поскольку такие соглашения о вызовах не применяются к 64-битным, существует только одно 64-битное соглашение о вызовах, продиктованное 64-битным ABI. Вы проверили, что GetProcAddress() успешен, а DoSmth не равен NULL?
Я скомпилировал dll как __stdcall. Но я не знаю, применимо ли это, я только что убедился, что параметры были правильно установлены. Однако я проверил, используя if (! HGetProcAddress) и if (! DoSomething), и они оба, похоже, не вводят оператор if. Кроме того, я правильно ввожу (и возвращаю) функцию, просто отладчик возвращает мне странное значение. Я забыл упомянуть кое-что важное: я использую символ UTF8 в параметре 'in'. Но кажется, что его легко поддерживать, если он вызывается в функции .cpp.





Хм ... Я нашел решение, но не знаю, как оно могло что-то решить ...
На самом деле я просто перекомпилировал dll (используя те же параметры, тот же формат и прочее), и теперь результаты в порядке, и он хорошо работает.
Если у кого-то есть объяснение или ключ к разгадке, я согласен.
Спасибо за ответы и помощь!
Это может быть что угодно. Вероятно, вы тестировали устаревший двоичный файл. Возможно, вы установили для DLL значение __stdcall, но забыли перекомпилировать.
Обратите внимание, что было бы неплохо удалить свой вопрос, поскольку он был решен таким образом, что вряд ли поможет другим посетителям.
Просто любопытно ... замените
std::string testна массивcharи посмотрите, изменится ли поведение.