Как скомпилировать сурсы в dll

Обновлено: 06.07.2024

Чтобы сэкономить ваше время от частого чтения, спасибо CristiFati, и вот ответ:
Если вы, как и я, используете "Библиотека" в "Типе конфигурации", вы получите файл .obj вместо .dll.
Правильное ключевое слово - «DynamicLibrary» вместо «Library». То есть:

Тогда у вас будет нужный .dll.

[дополнение] Из документов CMake, благодаря руководству Ботье, кажется, что «Библиотека» на самом деле похожа на подкаталог в корневом проекте. Таким образом, это отличается от того, как работает dll.

Рассказ :

  • Мне нужно скомпилировать dll с MSbuild без какой-либо IDE.
  • Я следовал инструкциям в Microsoft Doc, чтобы создать проект сборки приложения.
  • Веб-страница с указанием того, как создать проект сборки dll, еще не найдена. Таким образом, я редактирую .vcxproj в соответствии с аналогичной информацией Google.
  • СТРОЙ УСПЕХ!
  • Но результат содержит только файл .obj. Никакой dll в поле зрения нет.
  • Нужна помощь в том, как изменить .vcxproj для создания dll.

Подробная история :

Мне нужно скомпилировать dll.
Моя компания не покупала коммерческую лицензию, поэтому я не могу использовать для этого среду IDE.

Во-первых, после этой страницы я получил этот файл проекта типа приложения

В-третьих, переключите этот проект из режима приложения в режим библиотеки . На самом деле я не знаю, как это сделать. Так что я погуглил некоторую информацию и попытался сделать то, что они сделали. Я меняю режим отладки на режим выпуска. Затем измените вывод приложения на «Библиотека».

Наконец, я позволил msbuild выполнить свою работу:

И сборка удалась!

Но когда я перехожу в папку Release в моем корневом каталоге, я нахожу только файл «helloworld.obj» и «vc141.pdb» вместе с именами папок «helloworld.tlog».
Что ж, это не так. Думаю, правильным результатом здесь будет "helloworld.dll".

Так что, наверное, это проблема моего файла .vcxproj.
Итак, может ли кто-нибудь дать руководство по созданию проекта dll с нуля?
Спасибо!

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

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

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

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

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

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

В системе может одновременно выполняться несколько экземпляров приложения. Экземпляр библиотеки DLL может быть только один.

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

Динамическая компоновка кода и ресурсов имеет некоторые преимущества над статической.

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

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

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

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

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

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

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

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

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

Дополнительные сведения о создании и использовании библиотек DLL

В приведенных ниже статьях приводятся подробные сведения о создании библиотек DLL на C и C++ в Visual Studio.

Пошаговое руководство: Создание и использование библиотеки DLL (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 больше не нужен.

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

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

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

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

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

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

Технология Active и библиотеки DLL
Размещение серверов объектов внутри библиотеки DLL.

Автоматизация в библиотеке DLL
Параметр автоматизации в решениях мастера библиотек DLL MFC.

Соглашения об именовании библиотек DLL MFC
Способ встраивания библиотек DLL в MFC, опираясь на четко структурированное соглашение об именовании.

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

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

О втором способе расскажу подробнее:

Создание динамической dll путем пере компиляции в il

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

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools

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

Скомпилируем проект, получаем dll библиотеку. (у меня TestDll.dll)

Теперь необходимо преобразовать dll библиотеку в il код. Для этого нужно запустить ildasm в командной строке со следующими параметрами

ildasm TestDll.dll /OUT:TestDll.il

Далее необходимо проделать некоторые манипуляции с получившимся il кодом.

Во-первых, меняем флаг

Во-вторых, над началом описания классов (обычно эта область отделена комментарием CLASS MEMBERS DECLARATION) добавляем код:

.vtfixup [1] int32 fromunmanaged at VT_01

.data VT_01 = int32(0)

В-третьих, в методе который необходимо сделать экспортируемым добавляем код:

.export [1] as Run

Здесь Run – это название метода, по которому его будет вызывать сборка, написанная на неуправляемом коде.

Теперь необходимо скомпилировать dll библиотку, для этого воспользуемся утилитой ilasm, с параметрами:

ilasm TestDll.il /OUT:TestDll.dll /DLL

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

Динамическая dll + WPF

Если вы планируете создавать расширение с использованием технологий, требующих, чтобы приложение работало в STA потоке (Например WPF), то необходимо учесть, что поток в котором будет выполняться расширение наследуется от сборки запустившей библиотеку, а значит может быть не в режиме STA.

Для того чтобы обойти эту проблему было решено в расширении создать STA поток и в нем запускать окна на WPF.

Вот так можно модернизировать код для запуска WPF окна:

public static void Run()
Thread WPFThread = new Thread(OpenWTPWindow);
WPFThread.ApartmentState = ApartmentState.STA;
WPFThread.Start();
WPFThread.Join();
>

public static void OpenWTPWindow()
System.Windows.Window WPFWindow = new System.Windows.Window();
WPFWindow.ShowDialog();
>

Обратите внимание что окно запускается не с помощью функции Show() а ShowDialog(), функция Show() работает некорректно, при использовании её не в основном потоке.

Заключение

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

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

Ссылки по теме

Хорошая статья. Если у вас остались еще какие то вопросы по созданию динамической dll, рекомендую обратиться к ней.

Очень часто в своей работе, Вы будете сталкиваться с такой ситуацией.

Перед вами стоит задача, нужно написать программу " Супер Блокнот" которая должна сохранить все функции стандартного блокнота, но при этом иметь ряд каких-то дополнительных функций, благодаря которым, при выборе программы для работы с текстом, пользователь будет отдавать предпочтение именно вашей программе. Для этого было решено добавить несколько новых функций, одна из них, будет отвечать за подсчет и вывод количества слов в тексте.

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

Проходит время и перед вами ставят новую задачу, написать программу "Супер парсер". Одной из функции данной программы, будет подсчет слов в тексте. Вы понимаете, что снова придется разрабатывать метод, который будет вести подсчёт слов. Но, при этом вспоминаете, что совсем не давно уже разрабатывали программу, в которой применялась данная функция. Чтобы не изобретать велосипед, Вы открываете исходник программы "Супер блокнот"; и копируете весь метод в исходник новой программы "Супер парсер". Отлично, теперь Вам не придется тратить время на написание этого метода заново, и Вы можете посветить больше времени остальным элементам программы. Задача решена.

28409

Но, что если метод по подсчету слов, писали не Вы, а допустим, какой-нибудь коллега по работе и по каким-то причинам, Вы не можете получить доступ к исходному коду программы "Супер блокнот". То есть первый вариант, копирование метода из исходника, не прокатит и данный метод придется писать самому ммм, печалька.

Но, тут вам звонит ваш коллега по работе и говорит: Ты знаешь, я тут вспомнил, когда я разрабатывал данный метод, я подумал, что возможно мне придется его использовать ещё где-то, и по этому я решил вынести его в отдельную сборку, в виде файла динамической библиотеки (dll).Ты просто скопируй этот файл dll в свой проект, и подключи его, как внешнюю сборку, после чего ты получишь доступ к моему методу и сможешь им пользоваться.

Отлично! Вы проделываете все описанные действия, в программе “Супер парсер” появляется нужный метод, задача решена и вам вновь не пришлось повторно писать код руками.

28410

На этом присказка закончена и теперь переходим к более подробному изучению.

Что такое DLL

DLL (dynamic-link library) - это динамически подключаемая библиотека, или сокращено динамическая библиотека.


Как уже писал ранее, динамические библиотеки, позволяют повторно использовать ранее написанный код, а так же они обеспечивают лучшую переносимость кода. Достаточно, скинуть файл на флешку, или скачать dll файл из Интернета, после чего добавить его в текущий проект и тут же получить набор разных дополнительных функций для вашего приложения. Так же стоит знать, что в одном dll файле может храниться любое количество типов, членов и пространств имён.

Создание файла dll

Для начала выберем тип нового создаваемого приложения, а точнее проекта.

Выбираем Class Library, то есть создаем файл динамической библиотеки (dll)

Так же Вы можете указать, под какую версию Фреймворка будет создаваться данный проект.

28411

После того, как Visual Studio создаст каркас проекта, Вы увидите следующее:

Так будет выглядеть окно Solution Explorer

28412

А так будет выглядеть рабочая область, где Вы обычно пишите код программы

28413

И так дано пространство имён: Car и класс: Class1. Class1 не удачное название, давайте немного изменим наш код, заменив Class1 на BMW, и добавим метод, который будет выводить имя нашего класса.

28414

И так код написан, и теперь необходимо выполнить компиляцию, чтобы получить сборку.
Если сейчас попытаться нажать F5 или Ctrl+F5, то вы увидите данное окно

28415

A project with an Output type of Class Library cannot be started directly

Данная ошибка, говорит лишь о том, что был создан файл динамической библиотеки (dll), а не исполняемый файл (exe), который не может быть запущен.

Для того, чтобы скомпилировать проект, нажмите клавишу F6, после чего в директории bin\Debug появиться файл Car.dll.

Чтобы проверить был ли создан файл библиотеки, воспользуйтесь кнопкой Show All Files на вкладке Solution Explorer

28416

Сборка, в виде файла динамической библиотеки успешно создана.

Теперь перейдем в папку bin\Debug, для того, чтобы быстро переместиться в текущую директорию проекта, в том же Solution Explorer воспользуйтесь пунктом Open Folder in Windows Explorer

28417

Скопируйте полученный файл сборки (в нашем случае - это файл Car.dll) в какую-нибудь временную папку. На самом деле, это делать необязательно, Вы можете оставить данный файл в этой папке, но для удобства, создадим новую папку, и поместим туда созданный файл библиотеки.

Создаем новый проект.

28418

Новый проект создан. Теперь подключим в текущий проект, нашу библиотеку (Car.dll)

Подключение dll

Для этого на папке References, в окне Solution Explorer нужно нажать правую кнопку мыши и выбрать пункт Add Reference, откроется вот такое окно:

28419

  1. Выберите вкладку Browse
  2. Укажите папку, в которой лежит файл созданной библиотеки (в нашем примере - Car.dll)
  3. Выделите файл нужной библиотеки и нажмите кнопку ОК;

28420

На ней видно, что в наш текущий проект была успешна, добавлена ссылка на нашу сборку Car.dll, в которой храниться наш код на языке IL. Надеюсь, Вы помните, что после компиляции весь написанный вами код преобразуется в промежуточный код на языке IL (CIL, MSIL - это одно и тоже). А так же видно, что в папку bin\Debug была помещёна копия нашей библиотеки.

28421

Если вдруг Вы забыли, какое пространство имен, типы, или члены содержит ваша созданная библиотека. Вы всегда можете воспользоваться таким инструментом Visual Studio, как Object Browser. Для этого перейдите на вкладку Solution Explorer, откройте папку References, и просто щёлкните правой кнопкой мыши по добавленной ранее библиотеке, в нашем случае напоминаю - это файл (Car.dll) и выберите пункт View in Object Browser, появиться вот такое окно.

В окне Object Browser можно посмотреть содержимое нашей сборки.

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

Добавим, с помощью ключевого слова using пространство имен Car из созданной нами библиотеки Car.dll, после чего создадим объект класса BMW и выполним метод Вывести_Имя_Класса().

28423

28424

  1. Создаем файл динамической библиотеки (dll)
  2. Подключаем созданную библиотеку в наш проект, путем добавления в папку References ссылки на наш файл dll.
  3. (Необязательный пункт) Подключаем пространство имен из подключенной сборки, с помощью ключевого слова using, либо используем полное наименование, то есть Пространство имён.Тип (Car.BMW).
  4. Profit

И в конце не много информации о типах сборок:

Сборки бывают следующих основных видов: общие и частные.

Частная сборка (private assembly)

Это файлы библиотек, как наш ранее созданный файл Car.dll, которые содержаться на протяжении всего времени в каталоге текущего приложения или любом из его подкаталогов.

Вернёмся к началу статьи.

После того, как было создано приложение “Супер парсер”, мы получили сборку в виде файла (exe). Затем мы решили протестировать нашу программу и отдаём её нашему другу, при этом Вы так же упоминаете, что если он хочет иметь дополнительные функции в программе, то ему нужно просто рядом с его exe файлом поместить файл библиотеки Car.dll. После чего он получит возможность подсчёта слов в тексте. То есть библиотека будет храниться в той же директории, что и исполняемый файл.

28425

Общие сборки (shared assembly)

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

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