DLL: Предварить экспортируемые функции префиксом _
От: iAlexander Россия  
Дата: 18.12.08 12:27
Оценка:
Пролог:
Компилятор BCB5 использует по умолчанию соглашение __cdecl, и в объектных файлах предваряет все имена экспортируемых функций подчеркиванием( _ ).
Модификатор extern "C" не удаляет этого подчеркивания.
file.cpp: foo; file.o: _foo

Компилятор GCC также использует __cdecl и манглит имена по-своему, но с модификатором extern "C" имя функции в объектном файле точно соответствует имени в исходниках.
file.cpp: foo; file.o: foo


В наличии имеется достаточное количество dll и exe, которые скомпилированы под BCB5, и принимают это его _ как неизбежное зло, а поэтому при явной загрузке функции из своей sys.dll через GetProcAddress указывают префикс + ее имя:
GetProcAddress(handle, "_foo")

Поэтому при компиляции своей sys.dll компилятором GCC все остальные exe/dll, которые ее используют, перестают работать, поскольку функция _foo в ней отсутствует, зато присутствует foo.
Библиотека sys.dll компилируется GCC, поскольку глюки и слабость Билдера всем надоела. Но перекомпилить все GUI, которые используют sys.dll — практически невозможно.

Задача: необходимо все экспортируемые функции в dll, построенной GCC, предварить подчеркиванием, чтобы при явной загрузке функций из остальных приложений они были доступны без их перекомпиляции.

Самый топорный способ — в исходниках для всех функций foo() сделать оболочки _foo(), тогда GCC экспортирует и foo, и _foo. Клиенты библиотеки смогут обнаружить оболочку _foo и импортируют ее. Минусы — дополнительный invokation; мусор в коде и в export секции dll.
Просто переименовать все foo в _foo нельзя, поскольку исходники должны также компилироваться и в Билдере.

Попробовал еще сделать так:
extern "C" __declspec(dllexport)
int (*_foo)(int) = &foo();

Не получилось, gcc в секции export символ _foo вносит как data, а при попытке вызова _foo после ее загрузки из sys.dll происходит Access Violation.

Наверное, оптимальный вариант — не трогая исходники, после компиляции (или после построения объектников, но до линковки) заменять все символы foo в sys.dll и sys.lib на _foo.
Можно ли так сделать?

Using Visual C++ DLLs with C++Builder рассказывает, как использовать в Билдере dll, скомпилированные в MS VC. Полезная статья, но нужно почти наоборот.
Stdcall and DLL tools of MSVC and MinGW тоже близко, но не в точку. У dlltool есть опция --add-underscore, но она добавляет _ к именам в lib, а dll не трогает. dlltool может сделать DEF файл — в нем бы я смог указать конструкцию типа _foo = foo, но у GCC(MinGW) я не нашел опции, которая принимала бы DEF файл.
implib.exe[Borland] тоже может изменить lib, добавив подчеркивания к символам, но не изменяет dll, поэтому при явной загрузке функций не поможет.
gcc mingw builder dll lib mangling extern c dlltool implib
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.