Как создать файл DLL

Обновлено: 21.11.2024

Эта статья покажет вам основы создания библиотек DLL с помощью MinGW, а затем связывания с ними в ваших приложениях. Создаваемый здесь код можно будет использовать и в MSVC, поэтому вы или ваши конечные пользователи сможете использовать несколько компиляторов.

Основы DLL

DLL — это тип общей библиотеки, используемой в Microsoft Windows и OS/2, содержащей функции, которые можно повторно использовать в любом приложении, которое хочет их использовать (на самом деле библиотеки DLL могут содержать гораздо больше, чем просто функции, но эта статья о создании библиотек функций). Если у вас есть библиотека foo.dll, которая содержит функцию DoWork() , DLL должна экспортировать эту функцию, чтобы ее можно было использовать в приложениях. Аналогичным образом, если приложение bar.exe хочет использовать функцию DoWork() , оно должно импортировать эту функцию из foo.dll ( также можно написать код, который загружает DLL после запуска приложения, вызывает функции из этой DLL, а затем выгружает DLL, когда она больше не нужна — так обычно работают системы плагинов/аддонов). Экспорт и импорт функций довольно прост и требует небольшого количества кода, сопровождаемого правильной командной строкой компоновщика.

Негибкий и неэлегантный способ

Сначала мы создадим DLL, экспортирующую только очень простую функцию, которая складывает два целых числа и возвращает результат. Обратите внимание на атрибут « __declspec(dllexport) » в приведенном ниже коде — это ключ к экспорту функций из DLL, и каждая функция, которую вы хотите экспортировать из DLL, должна быть помечена этим атрибутом (любые внутренние функции, которые не составляют часть вашего API следует оставить как есть). Также обратите внимание на « __cdecl » перед именем функции, который объявляет соглашение о вызовах для функции (см. статью в Википедии о соглашениях о вызовах x86, если вы с ними не знакомы). Соглашение о вызовах по умолчанию для функций C в MinGW — cdecl, но рекомендуется всегда явно указывать соглашение о вызовах на случай, если какой-то другой компилятор использует другое значение по умолчанию — если это произойдет, ваше приложение, скорее всего, будет работать некорректно. или сбой в результате вызова одной из этих функций. Обратите внимание, что этот первый пример намеренно негибкий и неэлегантный, чтобы точно показать, что происходит за кулисами. В следующем разделе мы будем скрывать эти детали с помощью определений препроцессора.

Чтобы скомпилировать это, просто необходимо передать опцию «-shared» в обычную командную строку компоновщика:

Никаких ошибок не должно быть сообщено, и теперь у вас должна быть пригодная для использования библиотека DLL. В этом примере я разделил этапы компиляции и компоновки, хотя для такого небольшого проекта это можно было бы сделать просто с помощью « gcc -o add_basic.dll -s -shared add_basic.c -Wl, --subsystem,windows ». «-Wl,--subsystem,windows» на самом деле не является необходимым, но просто общепринято, что библиотеки DLL имеют подсистему графического интерфейса Windows, указанную в их PE-заголовке. Также обратите внимание, что переключатель «-s» используется для удаления символов из DLL — вы, вероятно, захотите сделать это только для выпускных сборок.

Теперь вы можете создать приложение, использующее эту библиотеку DLL. Все, что необходимо для использования функции Add(a, b), — это объявить функцию с атрибутом «__declspec(dllimport)» перед ее использованием (обратите внимание, что это dllimport для клиентского приложения, в отличие от dllexport, используемого в нашей DLL).

Теперь вы можете скомпилировать и связать это приложение, просто сославшись на нашу DLL в командной строке компоновщика.

Параметр «-L» указывает дополнительную папку, в которой компоновщик должен искать библиотеку DLL. В этом случае мы хотим, чтобы компоновщик выполнял поиск в текущем каталоге, поэтому мы можем просто использовать точку, но для настоящей DLL, которую мы развернули в системе, мы будем использовать полный путь к ее каталогу. Параметр «-l» указывает DLL, из которой мы хотим импортировать функции — это должно быть имя файла DLL без расширения файла. Опять же, для такого небольшого проекта приложение можно было бы скомпилировать и слинковать, выполнив команду gcc -o addtest_basic.exe -s addtest_basic.c -L. -ladd_basic ”

Гибкий и элегантный способ

Обратите внимание, что мы определили «ADDAPI» как «__declspec(dllexport)», если определено «ADD_EXPORTS», или «__declspec(dllimport)» в противном случае. Именно это позволяет нам использовать один и тот же заголовок для приложений и DLL. Также обратите внимание, что мы определили «ADDCALL» как «__cdecl», что позволяет легко переопределить соглашение о вызовах, которое мы используем для нашего API. Теперь в любом месте нашего кода, где нам нужно экспортировать функцию из нашей DLL, мы указываем «ADDAPI» вместо атрибута «__declspec(dllexport)» и «ADDCALL» вместо указания, т. е. «__cdecl». Принято называть эти определения препроцессора «[имя библиотеки]_EXPORTS», «[имя библиотеки]API» и «[имя библиотеки]». ЗВОНИТЕ», поэтому рекомендуется придерживаться этого правила, чтобы ваш код был удобочитаемым для вас и других.

Помните, что этот код нельзя переносить, так как в нем используются атрибуты Microsoft. Здесь это нормально, потому что это руководство по созданию Windows DLL, но если вам нужна межплатформенная совместимость, то ADDAPI и ADDCALL можно определить условно. Обычно это делается так:

Код для DLL теперь может включать только что созданный заголовок, и единственное изменение, которое нам нужно сделать, это включить «ADDCALL» перед именем функции (здесь необходимо указать соглашение о вызовах, чтобы предотвратить возможные конфликты между объявление и определение функции).

Чтобы скомпилировать эту DLL, необходимо определить «ADD_EXPORTS» при компиляции объектного кода, чтобы обеспечить правильное определение «ADDAPI» в заголовке. Проще всего это сделать, передав «-D ADD_EXPORTS» в командной строке:

Для компиляции приложения не требуется никаких изменений в используемой нами командной строке:

Этот процесс сборки используется во многих реальных библиотеках. Если неясно, что происходит с определениями препроцессора, передайте «-save-temps» в командной строке gcc на этапе компиляции и просмотрите файлы с расширением «.i» — вы заметите, что в конечном итоге сгенерированный код как в элегантных, так и в неэлегантных примерах почти одинаково.

Экспорт и импорт переменных

В дополнение к функциям также можно экспортировать и импортировать переменные. Эти переменные должны быть объявлены как «extern __declspec(dllexport)» или «extern __declspec(dllimport)», в зависимости от того, строим ли мы DLL или клиентское приложение с использованием этих переменных. Как и в случае с функциями, мы можем использовать определения нашего препроцессора и просто выделить переменные «extern ADDAPI». Для переменных не следует указывать соглашение о вызовах.

Здесь мы добавили две экспортированные переменные в наш заголовочный файл, foo и bar.

Код библиотеки DLL теперь включает присвоение значений нашим экспортируемым переменным:

Приложение было изменено таким образом, что теперь оно добавляет импортированные переменные foo и bar вместе, выводя результат:

Если вы измените значения foo и bar, перекомпилируете DLL и снова запустите приложение, вы увидите, что переменные действительно импортированы из DLL.

Импорт библиотек

Хотя обычно можно связать DLL, просто имея DLL в вашей системе и добавив некоторые параметры командной строки компоновщика, это не всегда желательно. В этом случае вместо этого следует использовать библиотеку импорта. Библиотека импорта не содержит кода, но содержит всю необходимую информацию, необходимую вашему приложению для поиска функций, экспортируемых DLL. При создании библиотек для использования третьими лицами я бы рекомендовал всегда создавать библиотеку импорта и распространять ее вместе с вашими файлами DLL и заголовочными файлами, поскольку вашим пользователям может потребоваться создавать свои приложения с использованием библиотек импорта.< /p>

Если вы изменили имена функций, которые экспортирует DLL (см. «Предупреждение об экспорте функций stdcall» ниже), библиотека импорта — единственный вариант. Это относится к API Windows, где вы должны связать свои приложения с помощью библиотек импорта, т. е. передать «-lgdi32 -luser32» и т. д. в командной строке компоновщика при компиляции программ с графическим интерфейсом Windows.

Создание и использование библиотеки импорта

Если вы не изменили ни одно из имен функций, экспортируемых DLL, то создание библиотеки импорта — это просто случай передачи дополнительного параметра «-Wl,--out-implib,lib[имя библиотеки ].a ” в командную строку компоновщика.

Принято использовать имя библиотеки в имени библиотеки импорта. Обязательно, чтобы имя файла начиналось с «lib» и заканчивалось расширением «.a», чтобы его можно было использовать (на самом деле есть несколько поддерживаемых соглашений об именах, которые вы можете использовать, которые описаны в руководстве, но все остальное не подходит). не работает).

Сборка приложения такая же, как и раньше, но вместо того, чтобы передавать каталог, содержащий DLL, компоновщику, вместо этого вы передаете каталог, содержащий библиотеку импорта (на самом деле мы все еще делаем все из текущего каталога, но это, вероятно, не было бы случаем для реального приложения). Чтобы связать DLL, вы передаете имя библиотеки импорта без префикса lib и расширения файла.

Обычно библиотеки DLL помещаются в папку с именем «bin», а библиотеки импорта — в папку с именем «lib», например, «C:\Program Files\Add\bin\» и «C:\Program Files\Add\». библиотека\ ".

Предупреждение об экспорте функций стандартного вызова

Одна вещь, о которой вы должны помнить при объявлении функций «__stdcall», заключается в том, что MinGW и MSVC экспортируют свои функции с немного разными именами (декорациями функций).Для нашего примера с добавлением выше MSVC экспортирует функцию «Add(int a, int b)» с именем «_Add@8» (подчеркивание, имя функции, знак at, размер аргументов в байтах), тогда как MinGW экспортирует ее. как «Add@8» (то же, что и MSVC, но без подчеркивания). Поэтому, если вы хотите иметь бинарную совместимость между сборками MinGW и MSVC вашей DLL, необходимо изменить имена экспортируемых функций. Это немного сложнее, чем я собираюсь охватить в этой статье, но я написал статью Advanced MinGW DLL Topics, в которой объясняется, как это сделать, а также некоторые подводные камни, на которые следует обратить внимание.

Добавление информации о версии и комментариев к вашей DLL

Если вы просмотрите свойства DLL с помощью проводника Windows и перейдете на вкладку «Подробности», вы, скорее всего, увидите информацию о DLL, такую ​​как версия, автор, авторские права и описание библиотеки. Это приятное прикосновение к DLL (особенно полезно, когда вы хотите знать, какая версия DLL установлена ​​на вашем ПК), и это довольно просто добавить в вашу DLL. Все, что вам нужно сделать, это создать ресурс версии, например следующий:

Я не буду вдаваться в подробности того, что означает каждый из этих элементов, так как они очень хорошо описаны в MSDN, но большая часть из них не требует пояснений (в любом случае я рекомендую прочитать статью MSDN, особенно если язык американский английский или любой другой, кроме британского английского).

Идея состоит в том, чтобы скомпилировать сценарий ресурсов с помощью windres.exe, а затем передать его компоновщику при связывании библиотеки DLL. Например, если ваш ресурсный скрипт называется «resource.rc»:

Это все, что нужно сделать, чтобы добавить информацию о версии в DLL. Стоит потратить время на то, чтобы сделать это для любых DLL, которые вы выпускаете, так как это полезно и придает вашему приложению профессиональный вид.

Собираем все вместе

Используя информацию из этой статьи, вы теперь сможете собрать все воедино и создать библиотеки DLL с помощью MinGW, а также исполняемые файлы, использующие функции, экспортированные из библиотек DLL. Чтобы помочь вам, я создал небольшой проект, который создает DLL со следующими функциями:

  • Экспортировано “ int Add(int a, int b); ”, используя соглашение о вызовах cdecl.
  • Экспортированные переменные «foo» и «bar».
  • Ресурс информации о версии, встроенный в библиотеку DLL.

Кроме того, будет создан исполняемый файл, который выводит результат сложения, используя экспортированную функцию и экспортированные переменные. Проект можно собрать с помощью утилиты mingw32-make.

Вы можете загрузить пример DLL MinGW с GitHub, чтобы создать пример DLL и приложения из этой статьи. Вы можете либо клонировать репозиторий с помощью git, либо загрузить пример выпуска MinGW DLL. Вы можете использовать его для любых целей, которые посчитаете нужными (полные условия использования см. в «License.txt»). Используя файлы проекта, вы можете легко создать пример из этой статьи и использовать его в качестве основы для своих собственных библиотек DLL и приложений.

Что нужно знать

Еще один момент, о котором следует помнить, это то, что если вы передаете структуры в функцию, экспортированную из библиотеки DLL, или возвращаете структуру из этой функции, вы не сможете позже изменить определение этой структуры. Внесение таких изменений, скорее всего, приведет к сбою старых приложений или к непредусмотренному поведению, поскольку расположение памяти структуры изменилось с момента компиляции приложения. Невозможно изменить определение структуры, не нарушая обратной совместимости, но это тоже не элегантно. Например, в Windows API часто бывает, что структуры имеют член (на первый взгляд бессмысленный), который указывает размер структуры, новые элементы добавляются в конце определения структуры и передаются в функции по адресу, а не по значению (для пример структуры OPENFILENAME). Это те вещи, которые позволяют Windows API изменяться между выпусками Windows, не нарушая обратной совместимости (я знаю, что люди могут сказать, что каждая версия Windows вызывает много проблем с обратной совместимостью, но факт в том, что хорошо написанное приложение, созданное для Windows 95 имеет хорошие шансы работать на последних версиях Windows, что, на мой взгляд, весьма впечатляет).

Похожие страницы


    Дополнительные темы по созданию библиотек DLL с помощью MinGW, включая классы JNI, P/Invoke и C++.
    Как создать полнофункциональное приложение Windows с графическим интерфейсом с помощью компилятора MinGW.
    Как создавать приложения OpenGL для Windows с помощью библиотек freeglut или GLUT для Win32 и компилятора MinGW.

©2001–2018 Transmission Zero. Все права защищены. Конфиденциальность и файлы cookie.

В Windows библиотека динамической компоновки (DLL) представляет собой разновидность исполняемого файла, который действует как общая библиотека функций и ресурсов. Динамическое связывание — это возможность операционной системы. Он позволяет исполняемому файлу вызывать функции или использовать ресурсы, хранящиеся в отдельном файле.Эти функции и ресурсы можно скомпилировать и развернуть отдельно от исполняемых файлов, которые их используют.

DLL не является автономным исполняемым файлом. Библиотеки DLL работают в контексте приложений, которые их вызывают. Операционная система загружает DLL в пространство памяти приложения. Это делается либо при загрузке приложения (неявное связывание), либо по запросу во время выполнения (явное связывание). DLL также упрощают совместное использование функций и ресурсов между исполняемыми файлами. Несколько приложений могут одновременно обращаться к содержимому одной копии DLL в памяти.

Различия между динамической и статической ссылками

Статическое связывание копирует весь объектный код из статической библиотеки в исполняемые файлы, которые используют его при создании. Динамическое связывание включает только ту информацию, которая необходима Windows во время выполнения для поиска и загрузки библиотеки DLL, содержащей элемент данных или функцию. При создании DLL вы также создаете библиотеку импорта, содержащую эту информацию. Когда вы создаете исполняемый файл, который вызывает DLL, компоновщик использует экспортированные символы в библиотеке импорта, чтобы сохранить эту информацию для загрузчика Windows. Когда загрузчик загружает DLL, DLL отображается в пространство памяти вашего приложения. Если присутствует, вызывается специальная функция в DLL, DllMain , для выполнения любой инициализации, требуемой DLL.

Различия между приложениями и библиотеками DLL

Несмотря на то, что библиотеки DLL и приложения являются исполняемыми модулями, у них есть несколько отличий. Самое очевидное отличие состоит в том, что вы не можете запускать DLL. С точки зрения системы между приложениями и библиотеками DLL есть два фундаментальных различия:

Приложение может иметь несколько экземпляров, работающих в системе одновременно. DLL может иметь только один экземпляр.

Приложение может быть загружено как процесс. Он может владеть такими вещами, как стек, потоки выполнения, глобальная память, дескрипторы файлов и очередь сообщений. DLL не может владеть этими вещами.

Преимущества использования библиотек DLL

Динамическая привязка к коду и ресурсам имеет ряд преимуществ по сравнению со статической привязкой:

Динамическое связывание экономит память и сокращает количество операций подкачки. Многие процессы могут использовать DLL одновременно, разделяя в памяти одну копию доступных только для чтения частей DLL. Напротив, каждое приложение, созданное с использованием статически связанной библиотеки, имеет полную копию кода библиотеки, которую Windows должна загрузить в память.

Динамическое связывание экономит дисковое пространство и пропускную способность. Многие приложения могут совместно использовать одну копию DLL на диске. Напротив, каждое приложение, созданное с использованием статической библиотеки ссылок, имеет код библиотеки, связанный с ее исполняемым образом. Это занимает больше места на диске и требует большей пропускной способности для передачи.

Обслуживание, исправления безопасности и обновления могут быть проще. Когда ваши приложения используют общие функции в библиотеке DLL, вы можете реализовать исправления ошибок и развернуть обновления в библиотеке DLL. Когда библиотеки DLL обновляются, приложения, которые их используют, не нужно перекомпилировать или связывать заново. Они могут использовать новую библиотеку DLL, как только она будет развернута. Напротив, когда вы вносите исправления в статически связанный объектный код, вы должны повторно связать и повторно развернуть каждое приложение, которое его использует.

Для послепродажной поддержки можно использовать библиотеки DLL. Например, библиотеку DLL драйвера дисплея можно изменить, чтобы она поддерживала дисплей, который был недоступен при поставке приложения.

Вы можете использовать явное связывание для обнаружения и загрузки библиотек DLL во время выполнения. Например, расширения приложений, которые добавляют новые функции в ваше приложение без его перестройки или повторного развертывания.

Динамическое связывание упрощает поддержку приложений, написанных на разных языках программирования. Программы, написанные на разных языках программирования, могут вызывать одну и ту же функцию DLL, если программы следуют соглашению о вызовах функций. Программы и функция DLL должны быть совместимы по следующим параметрам: Порядок, в котором функция ожидает, что ее аргументы будут помещены в стек. Отвечает ли функция или приложение за очистку стека. И передаются ли какие-либо аргументы в регистрах.

Динамическое связывание предоставляет механизм расширения классов библиотеки Microsoft Foundation Class library (MFC). Вы можете получить классы из существующих классов MFC и поместить их в библиотеку DLL расширения MFC для использования приложениями MFC.

Динамическое связывание упрощает создание международных версий вашего приложения. Библиотеки DLL — это удобный способ предоставления ресурсов, зависящих от локали, которые значительно упрощают создание международных версий приложения. Вместо того, чтобы поставлять много локализованных версий вашего приложения, вы можете поместить строки и изображения для каждого языка в отдельную DLL ресурсов. Затем ваше приложение сможет загружать соответствующие ресурсы для этой локали во время выполнения.

Потенциальным недостатком использования библиотек DLL является то, что приложение не является автономным.Это зависит от наличия отдельного модуля DLL: того, который вы должны развернуть или проверить самостоятельно в процессе установки.

Подробнее о том, как создавать и использовать библиотеки DLL

В следующих статьях содержится подробная информация о том, как создавать библиотеки DLL C/C++ в Visual Studio.

Пошаговое руководство. Создание и использование библиотеки динамической компоновки (C++)
Описывает создание и использование библиотеки DLL с помощью Visual Studio.

Виды библиотек DLL
Информация о различных типах библиотек DLL, которые можно создать.

Часто задаваемые вопросы о библиотеках DLL
Содержит ответы на часто задаваемые вопросы о библиотеках DLL.

Связать исполняемый файл с библиотекой DLL
Описывает явное и неявное связывание с библиотекой DLL.

Инициализировать DLL
Обсуждается код инициализации DLL, который должен выполняться при загрузке DLL.

Поведение DLL и библиотеки времени выполнения Visual C++
Описывает последовательность запуска DLL библиотеки времени выполнения.

LoadLibrary и AfxLoadLibrary
Обсуждается использование LoadLibrary и AfxLoadLibrary для явного связывания с библиотекой DLL во время выполнения.

GetProcAddress
Обсуждается использование GetProcAddress для получения адреса экспортируемой функции в DLL.

FreeLibrary и AfxFreeLibrary
Обсуждается использование FreeLibrary и AfxFreeLibrary, когда модуль DLL больше не нужен.

Порядок поиска библиотеки Dynamic-Link
Описывает путь поиска, который операционная система Windows использует для поиска библиотеки DLL в системе.

Состояния модуля обычной библиотеки DLL MFC, динамически связанной с MFC.
Описывает состояния модуля обычной библиотеки DLL MFC, динамически связанной с MFC.

Библиотеки расширения MFC
Описывает библиотеки DLL, которые обычно реализуют повторно используемые классы, производные от существующих классов MFC.

Создание библиотеки DLL только для ресурсов
Обсуждается библиотека DLL только для ресурсов, которая не содержит ничего, кроме ресурсов, таких как значки, растровые изображения, строки и диалоговые окна.

Локализованные ресурсы в приложениях MFC: вспомогательные библиотеки DLL
Обеспечивает расширенную поддержку вспомогательных библиотек DLL, которая помогает создавать приложения, локализованные для нескольких языков.

Импорт и экспорт
Описывает импорт общедоступных символов в приложение или экспорт функций из DLL

Активная технология и библиотеки DLL
Позволяет реализовать объектные серверы внутри библиотеки DLL.

Автоматизация в DLL
Описывает, что предоставляет параметр автоматизации в мастере DLL MFC.

Соглашения об именах для библиотек DLL MFC
Обсуждается, как библиотеки DLL и библиотеки, включенные в MFC, следуют структурированному соглашению об именах.

Вызов функций DLL из приложений Visual Basic
Описывает, как вызывать функции DLL из приложений Visual Basic.

Связанные разделы

Использование MFC как части библиотеки DLL
Описывает обычные библиотеки DLL MFC, которые позволяют использовать библиотеку MFC как часть библиотеки динамической компоновки Windows.

Версия DLL MFC
Описывает, как можно использовать общие библиотеки динамической компоновки MFCxx.dll и MFCxxD.dll (где x — номер версии MFC) с приложениями MFC и библиотеками DLL расширений MFC.

Во-первых, мы обсудим вопросы и требования, которые следует учитывать при разработке собственных библиотек DLL.

Типы DLL

При загрузке библиотеки DLL в приложение есть два метода связывания, позволяющие вызывать функции экспортированной библиотеки DLL. Два метода связывания —

  • динамическое связывание во время загрузки и
  • динамическое связывание во время выполнения.

Динамическое связывание во время загрузки

При динамическом связывании во время загрузки приложение выполняет явные вызовы экспортированных функций DLL, таких как локальные функции. Чтобы использовать динамическую компоновку во время загрузки, предоставьте файл заголовка (.h) и файл библиотеки импорта (.lib) при компиляции и компоновке приложения. Когда вы сделаете это, компоновщик предоставит системе информацию, необходимую для загрузки библиотеки DLL и определения местоположения функций экспортированной библиотеки DLL во время загрузки.

Динамическое связывание во время выполнения

При динамическом связывании во время выполнения приложение вызывает либо функцию LoadLibrary, либо функцию LoadLibraryEx для загрузки библиотеки DLL во время выполнения. После успешной загрузки DLL вы используете функцию GetProcAddress, чтобы получить адрес экспортированной функции DLL, которую вы хотите вызвать. При использовании динамической компоновки во время выполнения файл библиотеки импорта не требуется.

В следующем списке описаны критерии приложения для выбора между динамической компоновкой во время загрузки и динамической компоновкой во время выполнения.

Производительность при запуске. Если важна начальная производительность приложения при запуске, следует использовать динамическую компоновку во время выполнения.

Простота использования. При динамическом связывании во время загрузки экспортированные функции DLL аналогичны локальным функциям. Это поможет вам легко вызывать эти функции.

Логика приложения. При динамической компоновке во время выполнения приложение может разветвляться для загрузки различных модулей по мере необходимости. Это важно при разработке многоязычных версий.

Точка входа в DLL

При создании библиотеки DLL можно дополнительно указать функцию точки входа. Функция точки входа вызывается, когда процессы или потоки присоединяются к библиотеке DLL или отсоединяются от нее. Вы можете использовать функцию точки входа для инициализации или уничтожения структур данных в соответствии с требованиями библиотеки DLL.

Кроме того, если приложение является многопоточным, вы можете использовать локальное хранилище потоков (TLS) для выделения памяти, которая является частной для каждого потока в функции точки входа. Следующий код является примером функции точки входа DLL.

Если функция точки входа возвращает значение FALSE, приложение не запустится, если вы используете динамическую компоновку во время загрузки. Если вы используете динамическую компоновку во время выполнения, не будет загружаться только отдельная библиотека DLL.

Функция точки входа должна выполнять только простые задачи инициализации и не должна вызывать какие-либо другие функции загрузки или завершения DLL. Например, в функции точки входа не следует прямо или косвенно вызывать функцию LoadLibrary или функцию LoadLibraryEx. Кроме того, не следует вызывать функцию FreeLibrary, когда процесс завершается.

ВНИМАНИЕ. В многопоточных приложениях убедитесь, что доступ к глобальным данным DLL синхронизирован (потокобезопасный), чтобы избежать возможного повреждения данных. Для этого используйте TLS для предоставления уникальных данных для каждого потока.

Экспорт функций DLL

Чтобы экспортировать функции DLL, можно либо добавить ключевое слово функции к экспортируемым функциям DLL, либо создать файл определения модуля (.def), в котором перечислены экспортированные функции DLL.

Чтобы использовать ключевое слово функции, вы должны объявить каждую функцию, которую хотите экспортировать, с помощью следующего ключевого слова –

Чтобы использовать экспортированные функции DLL в приложении, вы должны объявить каждую функцию, которую вы хотите импортировать, с помощью следующего ключевого слова –

Как правило, вы должны использовать один заголовочный файл с оператором определения и оператором ifdef для разделения оператора экспорта и оператора импорта.

Вы также можете использовать файл определения модуля для объявления экспортируемых функций DLL. Когда вы используете файл определения модуля, вам не нужно добавлять ключевое слово function к экспортируемым функциям DLL. В файле определения модуля вы объявляете инструкцию LIBRARY и инструкцию EXPORTS для DLL. Следующий код является примером файла определения.

Написать образец DLL

В Microsoft Visual C++ 6.0 можно создать библиотеку DLL, выбрав тип проекта Win32 Dynamic-Link Library или тип проекта MFC AppWizard (dll).

Следующий код является примером библиотеки DLL, созданной в Visual C++ с использованием типа проекта Win32 Dynamic-Link Library.

Вызов образца библиотеки DLL

Следующий код является примером проекта приложения Win32, который вызывает экспортированную функцию DLL в библиотеке DLL SampleDLL.

ПРИМЕЧАНИЕ. При динамическом связывании во время загрузки необходимо связать библиотеку импорта SampleDLL.lib, которая создается при сборке проекта SampleDLL.

При динамической компоновке во время выполнения вы используете код, аналогичный приведенному ниже, для вызова экспортированной функции DLL SampleDLL.dll.

При компиляции и компоновке приложения SampleDLL операционная система Windows ищет DLL-библиотеку SampleDLL в следующих местах в указанном порядке —

Папка приложения

Текущая папка

Системная папка Windows (функция GetSystemDirectory возвращает путь к системной папке Windows).

Папка Windows (функция GetWindowsDirectory возвращает путь к папке Windows).

В этом разделе объясняется процедура создания настраиваемых файлов DLL, которые можно использовать для загрузки в приложение TruCap+.

Необходимые условия для создания DLL

Ниже приведен список предварительных условий, которые пользователь должен выполнить, прежде чем приступить к созданию любого DLL-файла.

Сигнатуры для определения методов

Существует определенный шаблон подписей, которым должен следовать пользователь при создании DLL для методов извлечения и проверки. DLL может содержать методы извлечения или проверки.

Подписи для метода извлечения:

public void ExternalExtractionMethodName(Список wordData, Список фразеданных, Список параметров, ref Список извлеченных результатов)

  • wordData и фразаДанные: это списки уже извлеченных слов и фраз, а также номер строки, координаты X и Y.
    Авторы DLL могут использовать эти данные в своей логике в соответствии с требованиями.
  • параметры: авторы DLL могут определять пользовательские параметры для своих методов. Эти параметры появляются в онтологии во время настройки этих функций. Значения, заданные для этих параметров во время определения онтологии, затем доступны в этом массиве.
  • extractedResults: этот параметр представляет собой список объектов ExtractedValue, и авторы DLL должны возвращать свои результаты в этом списке.

Подписи для метода проверки:

public static bool ExternalValidationMethodName (string args , string trustLevels )

  • args: это извлеченное значение для поля.
  • Уровни достоверности: это уровни достоверности для каждого символа в извлеченных значениях полей.
  • bool: ожидается, что это возвращаемое значение этого метода. Возвращаемое значение true означает, что проверка прошла успешно.

Шаблон проекта

  • Шаблон проекта Visual Studio CustomFunctions.zip предоставляется для использования авторами DLL.
  • Автор DLL должен скопировать этот шаблон в путь к шаблонам Visual Studio.

Поиск пути к шаблону проекта в Visual Studio

  1. Перейдите на страницу Microsoft Visual Studio, выберите Инструменты > Параметры.
  1. Пользователь может записать путь к шаблону проекта, указанный в поле Расположение шаблона проекта пользователя: для справки.

Создание нового проекта с использованием шаблона

  1. В расположении шаблонов проектов Visual Studio пользователю необходимо сначала скопировать файл CustomFunctions.zip.

По умолчанию отображается имя Class1.cs, однако пользователь может изменить имя проекта. Этот файл пользовательских функций содержит примеры реализации методов проверки и извлечения.

    Укажите имя и имя решения, выберите нужное расположение и нажмите кнопку "ОК".
    Код пользовательских функций появится на странице Visual Studio.

С помощью DLL (библиотека динамической компоновки) мы можем сделать наш проект модульным и сократить время разработки. DLL повышает производительность проекта и способствует повторному использованию кода. Это также помогает разработчику беспрепятственно вставлять и удалять новые функции в проекте.


По сути, DLL — это совместно используемая библиотека, которая содержит код и данные, используемые более чем одной программой одновременно, и, как и исполняемый файл, DLL не может запускаться напрямую. DLL (библиотека динамической компоновки) вызывается приложением.

Например, в Windows файл Kernel32.dll отвечает за управление памятью, операции ввода/вывода и прерывания.

ПРОМОКОД - PROMOTION25

Наиболее важные функции библиотеки DLL: она загружается во время выполнения, когда приложение запрашивается для функциональности библиотеки DLL, и время загрузки очень мало.

В этой статье я научу вас, как создать DLL на C++ и как использовать эту DLL в приложении C++.

Шаги по созданию DLL на C++

Здесь я опишу, как создать проект DLL на C++ с помощью Visual Studio.

  • Откройте визуальную студию и щелкните строку меню, чтобы создать новый проект. См. изображение ниже.

  • После выбора нового проекта откроется новое диалоговое окно, в котором выберите тип проекта Win32 и дайте имя проекту DLL.

  • На странице "Обзор" диалогового окна мастера приложений Win32 нажмите кнопку "Далее". После нажатия следующей кнопки откроется новое окно. Это окно настройки приложения, здесь мы выберем тип приложения и нажмем кнопку «Готово», чтобы создать проект DLL.

  • После создания проекта DLL вы должны добавить файлы заголовков и исходный файл в соответствии с вашими требованиями. Здесь я добавляю только один заголовочный файл (Calculation.h).

  • Когда вы создали файл заголовка, напишите желаемое содержимое в соответствии с требованиями. Здесь я создаю библиотеку, которая выполняет некоторые основные арифметические операции, такие как сложение, вычитание и умножение.

Примечание. Когда вы создали проект DLL, PROJECTNAME_EXPORTS автоматически определяется в символах препроцессора проекта DLL. В этом примере CALCULATIONDLL_EXPORTS определяется при построении проекта CALCULATIONDLL DLL.

  • Пришло время определить функцию члена класса в исходном файле. Здесь я определяю все функции-члены в файле CalculationDll.CPP.
  • Теперь исходные файлы и файлы заголовков добавляются в проект DLL, чтобы создать DLL и библиотеку, просто создайте проект DLL. Если все в порядке и ваш проект DLL компилируется без каких-либо ошибок, то будут созданы файлы DLL и .lib.

Этапы создания приложения C++

Здесь я создаю приложение C++, которое будет использовать созданную DLL.

  • Нажмите на строку меню, чтобы создать новый проект приложения C++, в котором используется DLL, которую я только что создал.

  • После выбора нового проекта откроется новое диалоговое окно, в котором выберите тип проекта Консольное приложение Win32 и дайте имя проекту приложения.

  • На странице "Обзор" диалогового окна мастера приложений Win32 нажмите кнопку "Далее". После нажатия следующей кнопки откроется новое окно. Это окно настроек приложения, здесь мы выберем тип приложения и нажмем кнопку «Готово», чтобы создать проект консольного приложения c++.

Теперь ваш проект приложения C++ готов к использованию DLL (библиотека динамической компоновки).

Как связать DLL с приложением C++

Здесь я обсуждаю простые шаги по связыванию проекта DLL с проектом приложения C++.

  • Когда мы создали DLL и приложение, после этого мы должны сослаться на DLL с приложением, которое позволяет приложению использовать функцию DLL в соответствии с требованием. Для этого в проекте CalculationApplication в обозревателе решений выберите элемент Ссылки. В строке меню выберите "Проект", "Добавить ссылку".

  • При нажатии кнопки "Добавить новую ссылку" откроется диалоговое окно со списками библиотек, на которые вы можете ссылаться. Вам нужно просто нажать на кнопку галочки в нужной библиотеке. Здесь в диалоговом окне отображается только одна библиотека.

  • Теперь ваша созданная библиотека связана с созданным приложением, но перед использованием DLL в приложении вы должны добавить заголовочный файл DLL. Есть два способа выполнить эту задачу: один из них — скопировать заголовочный файл DLL в ваш проект приложения, но это может привести к изменениям в одной копии, которые не отразятся в другой. Это небезопасный способ, поэтому мы следуем второму способу, в котором мы просто ссылаемся на файл заголовка DLL, чтобы указать путь к исходным файлам заголовков DLL в пути к каталогам, включенным в проект приложения.

Указав путь к заголовочному файлу DLL, вы сможете включить заголовочный файл DLL в свое приложение. Теперь пришло время получить доступ к функции DLL в соответствии с требованием.

В приведенном ниже коде приложения я просто вызываю функцию вычисления DLL для выполнения сложения, вычитания и умножения.

Читайте также: