Реферат: Создание в среде Borland C++ Builder dll, совместимой с Visual C++
Полученный .lib-файлдобавимкпроекту VC-клиента (Project -> Add To Project -> Files…).
Использование директивы препроцессора #define
Теперь рассмотрим способ, позволяющий добиться одинаковых названий функций в заголовочном и объектном (.lib) файлах с помощью директивы #define. Перепишем заголовочный файл нашей BCB-библиотеки следующим образом
Листинг 4 - Компилятор Borland C++ Builder 5
ImplicitLinking_cdecl.h
#ifndef _IMPLICITDLL_ #define _IMPLICITDLL_ #ifdef _DLLEXPORT_ #define _DECLARATOR_ __declspec(dllexport) #else #define _DECLARATOR_ __declspec(dllimport) #endif extern "C" { // при компиляции в VC к оригинальным наименованиям // функций добавятся символы подчеркивания, таким образом // имена объявляемых функций совпадут с их именами в таблице // экспорта DLL и, следовательно, .lib-файле #ifdef _MSC_VER #define SumFunc _SumFunc #define ViewStringGridWnd _ViewStringGridWnd #endif int _DECLARATOR_ __cdecl SumFunc(int a, int b); HWND _DECLARATOR_ __cdecl ViewStringGridWnd(int Count, double* Values); } #endif |
При компиляции клиентского VC-приложения в подключенном к проекту заголовочном файле dll (ImplicitLinking_cdecl.h) к наименованию каждой функции с помощью директив #define добавляется символ подчеркивания (макрос _MSC_VER определяется компилятором VC по умолчанию). Поскольку из BCB dll __cdecl-функции экспортируются таким же образом, то есть с добавлением символа подчеркивания, то устанавливается соответствие имен экспортируемых и объявленных функций. Макросы #define распространяют свое влияние и на весь последующий код приложения, что позволяет в тексте программы при вызове импортируемой функции пользоваться ее оригинальным именем, которое при компиляции будет дополнено необходимым магическим символом подчеркивания. Таким образом, мы идем на поводу у фирмы Borland и в клиентском приложении завуалированно используем для вызова функций из нашей dll имена, измененные компилятором BCB. Именно необходимость использования измененных имен (пусть и не в открытую благодаря define-трюку), на мой взгляд, является существенным недостатком этого способа, так как, например, при желании явно (см. раздел “Алгоритм с явной загрузкой dll”) использовать dll придется оперировать измененными именами функций. Не развивая дальше эту тему, скажу, что если BCB dll создается с четким намерением использовать ее в VC-приложениях, то лучше добавлять к проекту библиотеки .def-файл с удобными для пользователей именами-псевдонимами функций.
К достоинствам данного способа (define-трюка) можно отнести его простоту и, как бы это ни противоречило сказанному в предыдущем абзаце, отсутствие необходимости добавлять к таблице экспорта dll псевдонимы функций. Несмотря на все удобства использования псевдонимов, таблица экспорта (а следовательно, и сама dll) при этом увеличивается в размерах. Да и создание .def-файла псевдонимов при большом количестве функций не добавляет приятных эмоций.
После компиляции dll с помощью impdef.exe получаем .def-файл экспорта, из которого утилитой lib.exe создаем объектный .lib-файл и добавляем его к клиентскому VC-проекту.