Основная возникающая при этом проблема заключается в
том, что, согласно таблице 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
Рекомендуем скачать другие рефераты по теме: инновационная деятельность, заключение дипломной работы.