Форум программистов, компьютерный форум, киберфорум
Avazart
Войти
Регистрация
Восстановить пароль
Темы блога относятся к программированию на языке С++

В основном для C++Qt (Qt5.1) и C++ Builder (RAD 2009 и RAD XE3)
Рейтинг: 2.78. Голосов: 9.

DLL в C++Builder и Microsoft Visual C++

Запись от Avazart размещена 12.06.2012 в 22:32
Обновил(-а) Avazart 05.03.2020 в 19:49

Запись дорабатывается

Проблемы взаимодействия
Цитата:
Сложность использования dll, созданной с помощью Borland C++ Builder (далее BCB), в проектах, разрабатываемых в средах Microsoft, обусловлена тремя основными проблемами . Во-первых, Borland и Microsoft придерживаются разных соглашений о наименовании (naming convention) функции в dll. В зависимости от того, как объявлена экспортируемая функция, ее имя может быть дополнено компилятором определенными символами. Так, при использовании такого соглашения о вызове (calling convention), как __cdecl, BCB перед именем функции добавляет символ подчеркивания. Visual C++ (далее VC), в свою очередь, при экспорте функции как __stdcall добавит к ее имени помимо подчеркивания также информацию о списке аргументов (символ @ плюс размер списка аргументов в байтах).
2



Что нужно сделать для того что бы прикрутить вижуаловскую библиотеку:

1. Скачать эту самую билиотеку(динамической сборки). Как правило основу библиотеки составляют фалы c расширениями dll,lib и h. Копируем эти все файлы непосредственно в папку с проектом.
2. Произвести преобразование lib- файлов с помощью консольной утилиты coff2omf.exe поставляемой вместе с Builder-ом.Для этого заходим в меню Пуск->Выполнить (или win+R) cmd. - видим консоль
Выполняем команду в консоли для перехода в папку проекта (что бы в дальнейшем не указывать полные пути ) :
Код:
cd полный_путь_к_папке
Допустим у нас есть "x.lib" преобразовываем её в "x-bcb.lib" выполнив:
Код:
coff2omf x.lib x-bcb.lib
Если библиотек много то можно автоматизировать процесс создав батник(bat-файл) следующего содержания:
Bash
1
2
mkdir borland
for %%F in (*.lib) do coff2omf %%F borland\%%F
кинуть его в папку с lib-ами, и запустить и в итоге в созданной папке borland появятся уже с конвертированные либы под C++Builder. (пример с батником взят из какой-то документации по OpenCV)

3. Подключаем х-bcb.lib к проекту.Это можно сделать такими способами:

3.1. Меню Project->Add To Project ( Shift+F11 ) и выбираем "х-bcb.lib" После этого либа должна появится Project Manager-е.

3.2. Добавить в код:
C++
1
2
3
4
5
6
7
8
9
10
11
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
 
#include "x.h" // Заголовочный файл вашей библиотеки
#pragma comment (lib,"x-bcb.lib") // Эту строчку с указанием "x-bcb.lib"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//.....
Конкретный пример можно посмотреть здесь https://www.cyberforum.ru/blog... og533.html

Возможные проблемы:

1. Дело в том что библиотеки могут включать в себя несколько заголовочных файлов и лежать при этом в отдельной папке и при этом могут возникать ошибки(допустим внутри x.h - заголовка библиотеки) указывая на строку типа
C++
1
#include <y/z.h>
Где у- это папка в которой лежат заголовочные файлы, а z.h - какой нибудь другой хедер который лежит в папке y.

В этом случае необходимо прописать в опциях проекта в "инклюдах" путь к папке проекта (подразумевается что папка y- лежит именно там)

2. При компиляции пишит что-то вроде:
C++
1
[ILINK32 Error] Error: Unresolved external '_SHPCreate' referenced from C:\USERS\FUJITSU\DOCUMENTS\RAD STUDIO\PROJECTS\SHAPE\DEBUG_BUILD\UNIT1.OBJ
Это может говорить о том что вы забыли подключить lib файл к проекту.

Так же для некоторых либ необходимо определить или (директивой #define) какую нибудь константу используемую этой библиотекой. Например при подключении shapelib необходимо было сделать следующее:

C++
1
2
#define SHPAPI_CALL __stdcall // #define должно предшествовать #include x.h
#include "shapefil.h"
3. При попытке скомпилировать программа запускается и сразу же закрывается без выдачи ошибок и предупреждений.Это скорее всего говорит о том что не хватает какой нибудь dll-ки.

Узнать чего именно не хватает можно следующими способами:

1. Запустить exe-файл вашей программы- должно вылезти окошечко с указанием чего именно не хватает.
2. Использовать консольную утилиту tdump.exe для просмотра содержимого x.dll или вашего exe и просмотреть секцию импорта.
Код:
tdump x.dll > tdump.txt
Так как вывод обычно сильно длинный и не умещается в консоль, то вывод я перенаправляю в файл tdump.txt
3. Использовать программу Dependency Walker.

Затем следует поискать недостающие dll-ки в интернете,скачать их, и поместить их в папку с проектом, но при этом следуют учитывать версию dll-ки.

Особенности:

С++Builder обладает такой особенность которую следует учитывать при создании dll-лок и использовании в своем проекте dll написаных на VC:
  1. При компиляции dll к имени нашей функции добавляется символ подчеркивания. Т.е. если вы объявляете в cpp-файле вашей dll-ки функцию void func(), то в dll она будет выглядеть как "_func"
  2. При использовании dll в вашем проекте, Builder ожидает того что в dll записаны функции с "_". Т.е. если вы в вашем проекте вызываете функцию func(), то Builder будет её искать в dll-ке с именем "_func".
Естественно это касается только статического связывания.

Следует отметить что за добавления символа "_" отвечает опция показанная на скриншоте:

Нажмите на изображение для увеличения
Название: 1.gif
Просмотров: 1862
Размер:	29.8 Кб
ID:	772

Если установить эту опцию в false при создании dll, то в dll будут писаться функции без добавления подчеркивания впереди функции.
Если установить эту опцию в false при создании проекта, то получим кучу ошибок по тому как Builder "перестает видеть" свои родные функции которые записаны с подчеркиванием.

Литература:

1.
Архангельский Приемы программирование в С++ Builder6 и 2006
4.2.5 DLL в C++Builder и Microsoft Visual C++

Если вы хотите создать DLL, которая могла бы в дальнейшем использоваться и в проектах C++Builder, и в проектах Microsoft Visual C++, надо принять для этого некоторые меры. Прежде всего, следите за тем, чтобы при создании библиотеки в окне рис. 4.3 была включена радио-кнопка VCC++ Style DLL. Это обеспечит возможность динамического связывания библиотеки с проектами Microsoft Visual C++. Методика динамического связывания библиотеки с приложением Visual C++ ничем не отличается от рассмотренной в раз. 4.2.4: библиотека загружается функцией LoadLibrary, адрес используемой функции определяется вызовом GetProcAddress, а выгружается библиотека функцией FreeLibrary. Но при статическом связывании DLL с приложением Microsoft Visual C++ некоторые проблемы могут возникнуть. Причина в том, что в C++Builder и в Microsoft Visual C++ приняты разные форматы экспорта функций: COFF и OMF. Так что вам придется несколько изменить информацию об экспортируемых функциях.
Эту задачу позволяет решить утилита Impdef.exe, находящаяся в каталоге Bin вашей версии C++Builder. Утилита создает из указанного файла DLL текстовый файл описания с расширением .def, который вы далее можете редактировать. Первым параметром командной строки при вызове impdef передается имя создаваемого файла .def, а вторым — имя файла .dll. Например, если вы выполните команду:
Код:
impdef.exe  MyDLL.def MyDll.dll
то будет создан файл MyDLL.def описания вашей DLL. Он будет иметь вид:
Код:
LIBRARY     MYDLL.DLL

EXPORTS	
	
@@Umydialog@Finalize	 @5 ;	__linkproc__ Umydiaog::Finalize
@@Umydialog@Initialize 	 @4 ;	__linkproc__ Umydiaog::Initialize
_Code	                 @3 ;	_Code
_DoBeep	                 @2 ;	_DoBeep
_Form2	                 @7 ;	_Form2
_MyDialog	             @1 ;	_MyDialog
___CPPdebugHook          @6 ;	___CPPdebugHook
В этом тексте вы видите, в частности, строки описания функций _Code, _DoBeep, _MyDialog. Эти строки начинаются с имени функции, за которым следует уникальный номер, присваиваемый каждому входу в DLL. Затем после точки с запятой следует комментарий — первоначальное имя функции.
Если вы хотите преобразовать вашу DLL для работы с Microsoft Visual C++, надо удалить символы подчеркивания, с которых начинаются имена функций _Code, _DoBeep, _MyDialog. Теперь можно создать файл импортируемой библиотеки в формате Microsoft Visual C++. Это делается программой lib.exe, поставляемой вместе с Microsoft Visual C++. Вызвать ее надо командой:
Код:
LIB /DEF:MyDLL.def
В результате будет создан файл MyDLL.lib, который можно включать в проект Visual C++.
Теперь рассмотрим обратную задачу — использование в проекте С++Вuiilder библиотеки, созданной в Visual C++. Имеется два пути решения этой задачи. Если вы имеете исходную импортируемую библиотеку .lib, то можете использовать утилиту coff2omf.exe, находящуюся в каталоге Bin вашей версии C++Builder. Через командную строку в нее передается имя файла исходной библиотеки и имя файла новой библиотеки. Конечно, эти имена должны быть различными или хотя бы различаться расширениями. Иначе вы испортите исходную библиотеку. Например, если имя исходной библиотеки VCLIB.lib, то вызов утилиты Coff20mf может иметь вид:
Код:
сoff2omf VCLIB.lib VCLIB.tmp
В результате создастся файл VCLIB.tmp, который является импортируемой библиотекой в формате C++Builder. Вам остается перенести его в нужный каталог и изменить расширение на .lib.
Если изложенный способ преобразования файлов не привел к успеху, или если вы не имеете файла .lib исходной библиотеки, имеется другой путь решения той же задачи. Создайте с помощью описанной выше утилиты Impdef файл описания .def и посмотрите в нем экспортируемые функции. Если строки описания функций имеют вид подобный следующему:
Код:
_funcname@7   = _funcname  @1
то приведите их к виду:
Код:
funcname=_funcname@7
Затем сохраните отредактированный фай и создайте на его основе с помощью утилиты Implib файл .lib. В утилиту Implib через командную строку передается сначала имя создаваемого файла импортируемой библиотеки, а затем имя файла описания. Например:
Код:
Implib.exe VCLIB.lib VCLIB.def
Созданный файл .lib можно статически связывать с проектом C++Builder.
В целом, как видим, статическое связывание библиотек, созданных в разных системах, сопряжено с определенными сложностями. Так что надежнее всего использовать в этих случаях динамическое связывание. Тем более, что этот вариант имеет и ряд других преимуществ, описанных в предыдущих разделах.


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

Темы:

1. Как использовать библиотеки, скомпилированные в Visual Studio, в Билдере?
Просмотров 19290 Комментарии 15
Всего комментариев 15
Комментарии
  1. Старый комментарий
    Аватар для vxg
    от символа подчеркивания в именах функций спасает extern "C" и __stdcall при объявлении функций своей библиотеки
    Запись от vxg размещена 25.07.2012 в 12:46 vxg вне форума
  2. Старый комментарий
    Аватар для Avazart
    О соглашениях о вызове ф-ции можно прочитать в [2]
    Запись от Avazart размещена 27.07.2012 в 08:36 Avazart на форуме
  3. Старый комментарий
    Аватар для Fulcrum_013
    вопрос: а есть ли разница с тем чтобы .lib не конвертить а вытащить из dll при помощи implib?
    Запись от Fulcrum_013 размещена 20.12.2014 в 08:58 Fulcrum_013 вне форума
  4. Старый комментарий
    Аватар для Avazart
    Что вытащить?

    implib генерит на основе DLL lib-файл-импорта иногда удачно, иногда- нет, зависит от именования функций в DLL и опций которые передаешь в implib.

    coff2omf в большинстве своем(по опыту) справляется с задачей (без подбора опций).
    Запись от Avazart размещена 22.12.2014 в 20:31 Avazart на форуме
    Обновил(-а) Avazart 22.12.2014 в 20:37
  5. Старый комментарий
    Аватар для Alex_From_777
    Попробовал сделать. Новый файл при этом весит 1 кб, а исходный 73 кб.
    Подключил новый файл к проекту, как и ожидалось, он оказался нерабочим. В чем может быть причина? Может кто знает?
    Запись от Alex_From_777 размещена 25.12.2015 в 13:56 Alex_From_777 вне форума
  6. Старый комментарий
    Аватар для Avazart
    Что пробовал, где пробовал? О чем вы вообще...
    Вам нужна дистанционная помощь экстрасенса? Вам тогда не на этот форум...
    Запись от Avazart размещена 25.12.2015 в 14:29 Avazart на форуме
  7. Старый комментарий
    Аватар для Alex_From_777
    Цитата:
    Что пробовал, где пробовал? О чем вы вообще...
    "прикрутить вижуаловскую библиотеку" к проекту в билдере с предварительным её преобразованием утилитой сoff2omf.exe
    Запись от Alex_From_777 размещена 25.12.2015 в 14:38 Alex_From_777 вне форума
  8. Старый комментарий
    Аватар для Avazart
    А что за библиотека "мы" должны в хрустальном шаре увидеть?
    Запись от Avazart размещена 25.12.2015 в 18:41 Avazart на форуме
    Обновил(-а) Avazart 25.12.2015 в 18:43
  9. Старый комментарий
    Аватар для Dinkin
    Лайкуха =)
    Для некоторых производителей компонентов, не мешало бы что то подобное в юзер гайдах делать
    Запись от Dinkin размещена 20.12.2019 в 15:36 Dinkin вне форума
    Обновил(-а) Dinkin 20.12.2019 в 15:37
  10. Старый комментарий
    Аватар для Avazart
    Цитата:
    Для некоторых производителей компонентов, не мешало бы что то подобное в юзер гайдах делать
    Это каких компонент? Компоненты пишут на Delphi как бы.
    Запись от Avazart размещена 20.12.2019 в 20:11 Avazart на форуме
  11. Старый комментарий
    Аватар для Dinkin
    Не понял вопроса.
    Есть коммерческие проекты, в которых продают компоненты или библиотеки сразу под несколько сред. Клиенту высылается к примеру только три файла (.dll, .lib, .h). И дальше уже сам.
    Запись от Dinkin размещена 03.01.2020 в 03:20 Dinkin вне форума
  12. Старый комментарий
    Аватар для Avazart
    Компоненты как бы нормальные люди пишут на Delphi, а на Delphi для импорта из dll не нужны вообще *.lib
    Кроме того в пакетах обычно не *.dll а всякие VCL вариации типа *.bpk
    Запись от Avazart размещена 03.01.2020 в 21:25 Avazart на форуме
    Обновил(-а) Avazart 03.01.2020 в 21:27
  13. Старый комментарий
    Аватар для Dinkin
    Я напишу на форуме поддержки tmssoftware и vmprotect, что бы подумали о своей нормальности =))))
    Запись от Dinkin размещена 03.01.2020 в 21:38 Dinkin вне форума
  14. Старый комментарий
    Аватар для Dinkin
    И кстати coff2omf работает только с 32x, как поступить с 64x приложениями?
    Запись от Dinkin размещена 03.01.2020 в 21:40 Dinkin вне форума
  15. Старый комментарий
    Аватар для Avazart
    Цитата:
    Я напишу на форуме поддержки tmssoftware и vmprotect, что бы подумали о своей нормальности =))))
    Даже не знаю о ком Вы )))

    Цитата:
    И кстати coff2omf работает только с 32x, как поступить с 64x приложениями?
    Так для x64 компилятор другой, там по идее формат должен соответствовать MSVC (но это не точно).
    Запись от Avazart размещена 03.01.2020 в 21:56 Avazart на форуме
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.