Разница между вызовом функции "проекта" и вызовом функции DLL

В настоящее время у меня есть образец 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] всегда будет тем результатом, которого я ожидал бы получить.

Что я проверил:

  • Как и ожидалось, соглашение о вызове функции DLL - stdcall.
  • И образец, и DLL находятся в следующем контексте - Отладка - x64 -

Я думаю, что это могло произойти, но не знаю достаточно, чтобы гарантировать ответ Да / Нет:

  • Разница в управлении памятью между "простым вызовом" и GetProcAddress?
  • Проблема с отладчиком (было бы странно, учитывая, что значение out также ложно в случае вызова dll)
  • Другой?

Пожалуйста, подумайте о том, чтобы узнать подробности, если что-то неясно.

Просто любопытно ... замените std::string test на массив char и посмотрите, изменится ли поведение.

ap-osd 27.08.2018 17:03

@ ap-osd: Вы просили дать разъяснения в своем комментарии, этого должно было быть достаточно; Я пометил ваш ответ (который на самом деле просто повторяет вышеуказанный вопрос) для удаления. Тем более, что передача результата c_str() / data() функции, принимающей строку C (const char *), очень четко определена; эта часть вашего «ответа» неверна - и даже если она не так четко определена, даже передача &test[0]должен не будет проблемой.

DevSolar 27.08.2018 17:25

@DevSolar - Я просто хотел подчеркнуть тот факт, что внутренняя память std::string может изменяться, и ее ненадежно удерживать. См. Ссылки cplusplus.com/reference/string/string/c_str и en.cppreference.com/w/cpp/string/basic_string/c_str. В любом случае я ограничусь ответом на конкретную проблему.

ap-osd 27.08.2018 17:31

@ ap-osd: Это не более или менее ненадежно, чем прямая передача const char *. Если вы смотрите на однопоточный, он безопасен для является, если вы смотрите на многопоточность, он безопасен, если вы не начинаете изменять строковый объект (точно так же, как вы могли бы изменять строковый объект C, например, освобождая или повторно выделяя его память). Это отвлекающий маневр.

DevSolar 27.08.2018 17:37

@DevSolar - Теоретически это справедливо. Но у меня были аналогичные проблемы с передачей std::string через библиотеки DLL. Может быть, вы лучше объясните, почему это происходит, и я с радостью удалю свой «неправильный» ответ.

ap-osd 27.08.2018 17:47

@ ap-osd: передача std::string через границы DLL может быть проблематичной из-за различий в представлении объектов. Но OP - это нет, передающий std::string, но const char *, который только в этом случае находится в настоящее время под контрольstd::string. Здесь нечего смотреть...

DevSolar 27.08.2018 17:50

Исправление ... здесь нечего видеть, если OP прошел через c_str() / data(), что было бы правильным способом сделать это - хотя я не могу сейчас придумать, что соответствующая реализация не могла бы работать и с &test[0].

DevSolar 27.08.2018 17:55

Если функция действительно прототипирована как BOOL function(const char *in, char *out), то соглашение о вызовах не указано, поэтому она, скорее всего, использует __cdecl, а не __stdcall, как вы утверждаете. Если ваш компилятор не настроен на использование __stdcall в качестве соглашения о вызовах по умолчанию. Хотя это применимо только к 32-битной сборке, поскольку такие соглашения о вызовах не применяются к 64-битным, существует только одно 64-битное соглашение о вызовах, продиктованное 64-битным ABI. Вы проверили, что GetProcAddress() успешен, а DoSmth не равен NULL?

Remy Lebeau 27.08.2018 23:30

Я скомпилировал dll как __stdcall. Но я не знаю, применимо ли это, я только что убедился, что параметры были правильно установлены. Однако я проверил, используя if (! HGetProcAddress) и if (! DoSomething), и они оба, похоже, не вводят оператор if. Кроме того, я правильно ввожу (и возвращаю) функцию, просто отладчик возвращает мне странное значение. Я забыл упомянуть кое-что важное: я использую символ UTF8 в параметре 'in'. Но кажется, что его легко поддерживать, если он вызывается в функции .cpp.

Sillimon 28.08.2018 10:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
67
1

Ответы 1

Хм ... Я нашел решение, но не знаю, как оно могло что-то решить ...

На самом деле я просто перекомпилировал dll (используя те же параметры, тот же формат и прочее), и теперь результаты в порядке, и он хорошо работает.

Если у кого-то есть объяснение или ключ к разгадке, я согласен.

Спасибо за ответы и помощь!

Это может быть что угодно. Вероятно, вы тестировали устаревший двоичный файл. Возможно, вы установили для DLL значение __stdcall, но забыли перекомпилировать.

DevSolar 29.08.2018 09:26

Обратите внимание, что было бы неплохо удалить свой вопрос, поскольку он был решен таким образом, что вряд ли поможет другим посетителям.

DevSolar 30.08.2018 17:17

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