Реферат: Создание в среде Borland C++ Builder dll, совместимой с Visual C++

Основная возникающая при этом проблема заключается в том, что, согласно таблице 1, функции с __cdecl-соглашением о вызове будут экспортироваться с символом подчеркивания, следовательно, .lib-файл, созданный по .def-файлу экспорта библиотеки, будет содержать измененные имена функций. С другой стороны, во-первых, компилятор VC будет ожидать неизмененных наименований __cdecl-функций, потому что сам VC, экспортируя функции с __cdecl-соглашением о вызове, ничего к их наименованию не добавляет, а во-вторых, заголовочный файл BCB dll, подключаемый к клиентскому приложению, содержит объявления функций с их реальными (без символа подчеркивания) именами. В результате этого, если в тексте клиентского приложения встретится хотя бы один вызов нашей функции, то VC при связывании попытается найти описание этой импортируемой функции в добавленной к проекту библиотеке импорта (.lib-файле), с тем, чтобы добавить соответствующую запись в таблицу импорта приложения. Но из-за несоответствия имен функций в заголовочном и объектном файлах линковщик, естественно, в .lib-файле ничего не найдет, о чем не замедлит выдать сообщение (например, такое - error LNK2001: unresolved external symbol __imp__SumFunc).

ПРИМЕЧАНИЕ

Таблица импорта любого PE-файла содержит массив структур IMAGE_IMPORT_DESCRIPTOR. Каждая такая структура соответствует одной из dll, с которой неявно связан PE-файл. Структура IMAGE_IMPORT_DESCRIPTOR среди прочих полей содержит поле с RVA строки-наименования dll, которой она соответствует, и два поля с RVA массивов двойных слов, предназначенных для хранения информации об импортируемых функциях. При запуске приложения загрузчик PE-файлов заполняет один из этих массивов (так называемую таблицу адресов импорта) адресами импортируемых функций, загрузив перед этим dll, в которой эти функции находятся. Адрес импортируемой функции вычисляется как сумма адреса, по которому была загружена экспортирующая данную функцию dll, и смещения (RVA) самой функции относительно начала dll.

Описанную выше проблему несоответствия заголовочного и объектного файлов можно решить двумя способами – снова воспользоваться рассмотренным в предыдущем разделе .def-файлом с псевдонимами или использовать в заголовочном файле нашей библиотеки директиву препроцессора #define.

Использование псевдонимов

Следуя этому способу, создаем и добавляем к проекту BCB dll следующий .def-файл:

ImplicitLinkingAliases.def

EXPORTS

; MSVC name = Borland name

SumFunc = _SumFunc

ViewStringGridWnd = _ViewStringGridWnd

После компиляции наша dll будет экспортировать функции

ImplicitLinking_cdecl.def

libRARY IMPLICITLINKING_CDECL.DLL

EXPORTS

SumFunc @4 ; SumFunc

ViewStringGridWnd @5 ; ViewStringGridWnd

_SumFunc @1 ; _SumFunc

_ViewStringGridWnd @2 ; _ViewStringGridWnd

___CPPdebugHook @3 ; ___CPPdebugHook

Таким образом, в таблицу экспорта dll добавляются функции-псевдонимы, имена которых соответствуют функциям, объявленным в заголовочном файле нашей библиотеки. Для полного соответствия (хотя этого можно и не делать) удалим из ImplicitLinking_cdecl.def упоминания обо всех посторонних для приложения-клиента функциях, так как заголовочный файл содержит объявления только двух функций. В результате получим .def-файл готовый для генерации из него объектного .lib-файла:

ImplicitLinking_cdecl.def

libRARY IMPLICITLINKING_CDECL.DLL

EXPORTS

SumFunc @4 ; SumFunc

ViewStringGridWnd @5 ; ViewStringGridWnd

ПРИМЕЧАНИЕ

В единственной статье, которую мне удалось найти по данной теме (на сайте bcbdev.com), рекомендовалось, помимо удаления из .def-файла посторонних функций, заменить наименование секции EXPORTS на IMPORTS. Делать этого не следует по той простой причине, что утилита lib.exe (по крайней мере, поставляемая с 6-ой и 7-ой Visual Studio) секцию IMPORTS не поддерживает, поэтому игнорирует все последующие описания функций и создает пустой .lib-файл. Утилита lib.exe находится в каталоге $(VC)\Bin, но запустить ее обычно с первого раза не удается, поскольку для работы ей требуется библиотека mspdb60.dll (для lib.exe, поставляемой с Visual Studio 7 – mspdb70.dll). mspdb60.dll лежит в папке $(Microsoft Visual Studio)\Common\MSDev98\Bin, а mspdb70.dll – в папке $(Microsoft Visual Studio .NET)\Common7\IDE.

С помощью утилиты lib.exe создадим необходимый для неявного связывания .lib-файл в формате COFF, для этого в командной строке наберем

lib.exe /def:ImplicitLinking_cdecl.def

К-во Просмотров: 490
Бесплатно скачать Реферат: Создание в среде Borland C++ Builder dll, совместимой с Visual C++