Stdcall name mangling using extern c и dllexport vs определения модулей (msvС++)

Я пытался экспортировать простую тестовую функцию для dll для работы с приложением (fyi: mIRC), который определяет соглашение о вызове как:

int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)

Теперь, чтобы вызвать это из приложения, я бы использовал test_func, но я заметил, что из-за изменения имени это не так просто, как я думал.

В рамках подобных тем я пришел к пониманию, что использование extern "C" в сочетании с __ declspec (dllexport) - это эквивалентный (несколько) метод удаления mangling к определениям модулей (.def). Однако при использовании метода extern/dllexport моя функция (в качестве примера) всегда _test_func @numbers, тогда как .def удаляет все искажения, как требуется для использования с приложением, которое мне нужно экспортировать.

Может кто-нибудь объяснить, почему это так? Мне просто интересно узнать об этих двух методах. Спасибо!

Ответы

Ответ 1

dllexport/import предназначены для загрузки самостоятельно, а не из старой библиотеки C с использованием GetProcAddress. Вы можете заметить, что все компиляторы Microsoft уже давно используют функции __stdcall. Скорее всего, ваша цель либо ожидает функцию __cdecl, но не __stdcall, но если это не так, вам нужно будет использовать файл .def для особого запрета имени.

Ответ 2

extern "C" не имеет ничего общего с stdcall: он только объявляет, что смена имени С++ (aka type-safe linkage; включение информации о типе в имя символа) отключается. Вы должны использовать его независимо от того, используете ли вы соглашение C-вызова или соглашение о вызове stdcall.

В стандартном вызове stdcall вызывающий оператор удаляет параметры из стека. Чтобы сделать это безопасным, экспортируемое имя содержит количество байтов, которое вызываемый будет удалять из стека.

Если для приложения, которое вы экспортируете, требуется, чтобы в имя не добавлялся суффикс @number, это, вероятно, означает, что он ожидает соглашения о вызове C. Поэтому вы должны прекратить объявлять функцию как __stdcall. Когда вы объявляете его как declspec(dllexport), вы должны получить неразделенное имя в DLL.

В DEF файле вы можете вызвать функцию, которую хотите; дополнительная проверка не выполняется.