Показать сообщение отдельно
  (#9 (permalink)) Старый
Влад Влад вне форума
Специалист
Влад is on a distinguished road
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 19 раз(а) в 19 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 12:06

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 так:
Код:
EXPORTS MyFunc
Компоновщик от 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, причем оба они будут указывать на одну и ту же функцию.
Ответить с цитированием