Q: Как сделать DLL с нормальными экспортами, как у системных DLL Windows? Если пишу extern "C" __declspec(dllexport) int __stdcall func(int), получается (я надеюсь) stdcall, но имена _func@4; а хочется func.
A: Джеффри Рихтер пишет по этому поводу:
"Дело в том, что компилятор Microsoft С, экспортируя С-функцию, искажает eе имя, даже если Вы вообще не пользуетесь С++. Это происходит, только когда Ваша функция экспортируется по соглашению __stdcall. (Увы, это самое популярное соглашение.) Тогда компилятор Microsoft искажает имя С-функции, впереди ставит знак подчеркивания, а к концу добавляет суффикс, состоящий из символа @ и числа байтов, передаваемых функции в качестве параметров.
Например, следующая функция экспортируется в таблицу экспорта DLL как _MyFunc@8:
Код:
__declspec(dllexport) LONG __stdcall MyFunc(int a, int b);
Чтобы средствами Microsoft собрать DLL, способную работать с инструментарием от другого поставщика, нужно указать компилятору Microsoft экспортировать имя функции без искажений."
Сделать это можно несколькими способами.
Первый — создать DEF-файл для Вашего проекта и включить в него раздел EXPORTS так:
Компоновщик от Microsoft, анализируя этот DEF-файл, увидит, что экспортировать надо обе функции: _MyFunc@8 и MyFunc. Поскольку их имена идентичны (не считая вышеописанных искажений), компоновщик на основе информации из DEF-файла экспортирует только функцию с именем MyFunc, а функцию _MуFunc@8 не экспортирует вообще.
Второй — надо добавить в Linker->Command line->Additional Options к опциям линкера дополнительные параметры. Например, Вы экспортируете две функции и хотите обойтись без искажения имен, в command line нужно добавить:
Код:
/export:Func1 /export:Func2
Этот способ имеет небольшое ограничение: сравнительно небольшое число экспортируемых функций. Представьте себе программиста, судорожно пытающегося найти опечатку в опциях линкера "/export" для хотя бы полусотни экспортируемых имен...
Третий способ — Вы можете в .CPP файле написать
Код:
#pragma comment(linker, "/export:Func1=_Func1@4")
и линкер экспортирует как недекорированное имя Func1, так и декорированное имя _Func1@4, причем оба они будут указывать на одну и ту же функцию.