Изменение имени в stdcall с использованием определений extern c и dllexport против модулей (msvc ++) - PullRequest
15 голосов
/ 29 декабря 2010

Я пытался экспортировать простую тестовую функцию для 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) - это эквивалентный (несколько) метод удаления искажения в модуле определения (.def). Однако при использовании метода extern / dllexport моя функция (в качестве примера) всегда имеет значение _test_func @ numbers , тогда как .def удаляет все искажения, как это требуется для использования с приложением, которое необходимо экспортировать в.

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

Ответы [ 2 ]

13 голосов
/ 29 декабря 2010

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

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

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

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

12 голосов
/ 29 декабря 2010

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

...