Как собрать dll из исходников c

Обновлено: 04.07.2024

Как же подключить/загрузить внешнюю динамическую библиотеку в свою программу/проект, написанную на языке программирования C++ в IDE Microsoft Visual Studio, в ОС Microsoft Windows?

Состав

Типы файлов

Для начала, давайте разберёмся, что обычно представляет собой любая динамическая библиотека, написанная на, и созданная для программ С++? Это от 1 до 4 типов файлов:

Из всего списка главным являются только файлы с расширением .dll, т.е. остальных файлов может и не быть.

Количество

У одной библиотеки может быть множество файлов таких типов. Все они, обычно, рассортированы по соответствующим папкам, чтобы было легче подключать в IDE.

Вариации

Файлы dll, lib и exp различаются по платформе (ОС), архитектуре, конфигурации, etc. В одной версии библиотеки может предоставляться сразу несколько альтернативных вариаций одинаковых по функционалу файлов. E.g.:

Всё это крайне важно, всё надо учитывать при подключении библиотеки к проекту. Свойства проекта в Visual C++ могут устанавливаться отдельно для каждой конфигурации (Release, Debug) и архитектуры/платформы (x32 (x86), x64).

Подключение

Перед тем, как подключать файлы библиотеки к своей программе, надо сперва открыть необходимый проект в IDE Visual Studio: Главное меню > Файл > Открыть проект.

Заголовочные файлы (.h)

Файлы таблиц импорта и экспорта (.lib, .exp)

Файл таблицы импорта (.lib)

Помимо указания IDE директории расположения файлов таблиц импорта (.lib), их также для линковки надо дополнительно явно указать. Сделать это можно двумя способами:

      Прописать полные названия (путь, название и расширение) .lib файлов сюда: Главное меню > Проект > Свойства проекта > Свойства конфигурации > Компоновщик > Ввод > Дополнительные зависимости. Каждая библиотека в отдельной строке. Кавычки необязательны.
      В итоге они будут вписаны автоматически в строку в двойных кавычках через точку с запятой (;). E.g.:

    Можно использовать сразу два способа.

    Я рекомендую использовать второй вариант, когда все подключения пишутся непосредственно в коде. Так нагляднее и переносимость кода увеличивается, когда всё, что нужно написано в самом коде, а не где-то там в настройках IDE.

    Файлы библиотек (.dll)

    Параметры конфигурации препроцессора

    Также не забывайте указывать параметры конфигурации препроцессора тут: Главное меню > Проект > Свойства проекта > Свойства конфигурации > C/C++ > Препроцессор > Определения препроцессора. Параметры являются комбинированием в определённой последовательности определённых литералов. Вот некоторые из них:

    Некоторые возможные варианты параметров:

    • MT_StaticRelease
    • MTd_StaticDebug
    • MD_DynamicRelease

    Это далеко не все возможные параметры.

    Примечания

    Пути директории указывать без конечного слеша.

    Опция Компоновщик
    Библиотеки

    Заключение

    На самом деле, подключать сразу столько всего зачастую не нужно. Как правило, предоставляется только исходный код и всё. Приходится самостоятельно из исходников компилировать библиотеки (файлы .dll и .lib). Т.е. нужно будет указать только заголовочные файлы .h, которые являются частью исходников.

    Ссылки на проект, который можно использовать как основу и "болванку" для вашей библиотеки. Уже все настроено как надо, собрано в кучку. Проект для VS2015. Также можно открыть в более новой версии VS.

    zip-архив - исходные тексты примера из этой статьи и готовая скомпилированная библиотека dll

    В приведенном готовом проекте по ссылкам выше предусмотрены следующие варианты сборки в зависимости от требуемой версии QUIK (указано в формате: Solution Configurations | Solution Platforms):

    Release / Debug | Win32 - для QUIK 6.x / 7.x (x32, Lua5.1)

    Release / Debug | x64 - для QUIK 8.0. 8.4 (x64, Lua5.1)

    Release-Lua53 / Debug-Lua53 | x64 - для QUIK 8.5 и далее (x64, Lua5.3)

    Release-Lua54 / Debug-Lua54 | x64 - для QUIK 8.11 и далее (x64, Lua5.4)

    Есть вопросы? что-то не понятно? Вэлком в комментарии.

    2 Ответ от admin 2012-12-19 21:01:52

    Написание собственных .dll-библиотек на С++ для подключения их к коду Lua (QLua) и вызов своих функций из этих библиотек

    Здесь примеры будут рассматриваться на C++ (т.к. именно этот и только этот язык рассмотрен в документации LUA), но если у кого-то будет острое желание делать внешние модули на другом языке - пишите в комментариях. (Есть отдельная тема про Delphi / Lazarus.)

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

    Начну в каком-то смысле «с конца».
    Чтобы подключить внешнюю DLL библиотеку к LUA, в скрипте необходимо необходимо вписать строчку:

    В результате выполнения этой строчки в LUA будет закружена библиотека с именем luacdll.dll (причем расширение в require не указывается), и из этой библиотеки будет прочитана информация об имеющихся в ней функциях, доступных из LUA (позже мы увидим каким именно образом).
    Для простоты и надежности я очень советую положить скомпилированный dll-файл в тот же каталог, где расположен сам терминал QUIK, это проще и надежнее всего. Хотя можно настроить в LUA-скрипте содержимое переменной package.cpath до строки с require, если очень хочется.

    Уточнение для QUIK 8.11 и более новых версий по поводу расположения файла скомпилированного dll-файла. Начиная с этой версии, для выполнения скриптов доступен выбор версии интерпретатора Lua: 5.3 или 5.4. Это добавляет проблем с выбором места, где расположить изготовленную нами библиотеку. Если вы гарантированно используете лишь одну версию (либо 5.3, либо 5.4) для выполнения всех своих скриптов - то можете также положить библиотеку в корень терминала QUIK. Это будет просто и надёжно. Однако, если вы планируете запускать скрипты с разными версиями интерпретатора, что придется держать 2 версии библиотеки (скомпилированные для Lua5.3 и Lua5.4) и подгружать в скрипт соответствующую версию библиотеки (при использовании неподходящей сборки dll-библиотеки непременно будут проблемы в работе библиотеки). Подробнее этот момент рассмотрен в отдельной ветке форума.

    Настройка C++ проекта

    Первые три файла содержат описание типов и прототипы интерфейсных функций LUA, четвертый - библиотека для статический линковки с внешней библиотекой интерпретатора lua5.1.dll.

    Открываем MS Visual Studio, создаем новый проект DLL.
    В свойствах проекта для всех конфигураций, какие мы будем собирать (обычно это Release и Debug), необходимо добавить библиотеку lua5.1.lib в дополнительные библиотеки. В приложенном примере она лежит в подпапке contrib:

    Настройка свойств C++ проекта для сборки библиотеки, доступной из LUA

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

    Подключаем единый файл lua.hpp, в котором:

    подключаются все необходимые заголовочные файлы Lua;

    т.к. наш проект C++, то заголовочные файлы Lua необходимо подключать под extern "C", что уже сделано в этом едином файле.

    https://quik2dde.ru/static-img/cpp_lua-2-03.jpg

    Для release-конфигураций выбираем:

    https://quik2dde.ru/static-img/cpp_lua-2-04.jpg

    Для debug-конфигураций выбираем:

    Теперь собственно код библиотеки на C++

    Т.к. библиотеку мы назвали luacdll и именно это имя указываем в Lua-скрипте в require, то при загрузке нашей библиотеки LUA-интерпретатор будет искать экспортируемую из нее функцию с определенным именем, состоящем из "двух частей". В нашем случае это имя будет luaopen_ luacdll (). Здесь luaopen_ это предопределенный префикс (см. документацию), а luacdll собственно имя нашей библиотеки. Разумеется, тип и аргументы этой функции тоже предопределены.

    Для Lua 5.1 эта функция должна содержать следующие строки :

    Здесь мы регистрируем в LUA-интерпретаторе (путем вызова luaL_openlib) те функции, которые мы предоставляем из нашей библиотеки, что делает их доступными для вызова из LUA-скриптов. Вторым параметром функции передается namespace (имя глобальной переменной), в котором будут доступны функции нашей библиотеки при вызове; чтобы не запутаться, namespace делаем совпадающим с именем нашей библиотеки.

    Для Lua 5.2 и более новых версий эта функция должна содержать следующие строки :

    Здесь мы тоже регистрируем в LUA-интерпретаторе (путем вызова luaL_newlib) те функции, которые мы предоставляем из нашей библиотеки, что делает их доступными для вызова из LUA-скриптов. В отличии от варианта для Lua 5.1 никакая глобальная переменная не задаётся, функции библиотеки становятся доступными в той переменной, которой присвоим результат выполнения require() в коде Lua-скрипта.
    luaL_newlib() - это удобный макрос, который сразу включает в себя вызов трех интерфейсных функций Lua:

    luaL_checkversion - для проверки версии интерпретатора Lua, особенно актуально для QUIK 8.11;

    luaL_newlibtable и luaL_setfuncs - функции, последовательно вызываемые для регистрации функций, реализованных в библиотеке.

    (Функция luaL_openlib() удалена из Lua 5.2 как устаревшая.)

    В нашей простейшей библиотеке будут реализованы 3 функции, доступные из LUA:

    GetCurrentThreadId - получить ID текущего потока

    MultTwoNumbers - перемножает 2 числа, заданных в качестве аргументов

    MultAllNumbers - перемножает все числа, встретившиеся в аргументах

    Сам список функций (имя и указатель на соответствующую Си-функцию) описан в константном массиве:

    Реализация функции, возвращающей ID текущего потока:

    Ее прототип предопределен и един для всех интерфейсных функций: принимает единственный параметр L - указатель на стек LUA (см. документацию).
    В данном случае функция не подразумевает никаких аргументов и возвращает единственное целочисленное значение.

    Исходный код остальных функций можно посмотреть в приложенном архиве, на мой взгляд, в особых комментариях он не нуждается. В реализации MultAllNumbers можно посмотреть как производится обработка вызова функции из LUA с произвольным числом и типом параметров.

    После компиляции получившийся DLL-файл (как было сказано) копируем в тот же каталог, где расположен терминал QUIK (обязательно перепишите туда же файл lua5.1.dll!), и запускаем в нем следующий LUA-скрипт, предварительно сохраним его в виде файла:

    Полностью исходные тексты и скомпилированную dll можно скачать по ссылкам в первом посте этой темы.

    БлогNot. Как собрать проект C++ с github из исходников и подключить его к Visual Studio

    Как собрать проект C++ с github из исходников и подключить его к Visual Studio

    Благодаря менеджеру пакетов winget, уже входящему в актуальные сборки масдайки, теперь в Windows 10 можно инсталлировать приложения одной простой консольной командой (см. также доку от Микрософта).

    Но мы рассмотрим сейчас ситуацию, когда у нас есть только ссылка на исходники проекта, скажем, на Гитхабе (возьмём для примера библиотеку для простых чисел primesieve) и нужно каким-то образом скомпилировать внешний проект в своей Studio, чтобы воспользоваться его возможностями в своём приложении.

    В противном случае, конечно же, нестандартный include вроде этого, который вы нашли в коде-образце

    работать не будет ни за что.

    Первым делом скачаем все исходники внешнего проекта "как есть" в архиве .zip, для этого у нас на гитхабе есть кнопка "Download ZIP":

    Как загрузить проект с github в архиве .zip


    Как загрузить проект с github в архиве .zip

    Развернём проект, не создавая новой папки, если у вашего архиватора нет такого же пункта меню, просто сотрите предлагаемое архиватором имя новой папки, потому что папка уже есть в архиве:

    Извлечь внешний проект из архива, не создавая новой папки


    Извлечь внешний проект из архива, не создавая новой папки

    Если покопаться в файле readme.md проекта, как правило, можно найти инструкцию по установке (Build instructions) и даже "Detailed build instructions", где говорится, в числе прочего, и о компиляции проекта под Microsoft Visual C++:

    Команды cmake для компиляции проекта со страницы документации


    Команды cmake для компиляции проекта со страницы документации

    Откроем свой "некомпилируемый" без нужной библиотеки проект в Studio (я использую актуальную сборку версии 2019) и обратимся к команде меню Вид - Терминал. Выберем инструмент "Командная строка разработчика" (по умолчанию в новых сборках теперь выбран PowerShell, впрочем, если в документации приведены команды PowerShell, то применяйте их).

    У Микрософта инструмент описан вот здесь.

    Командная строка разработчика в Studio


    Командная строка разработчика в Studio

    В командной строке пишем команды из документации, но сначала, конечно, нужно перейти в ту папку, где у вас развёрнут скачанный проект. Мне понадобилось ввести в консоли следующее, завершая каждую команду нажатием Enter:

    - теперь я в нужной папке, так как развернул свой архив в папку d:\temp

    Далее как написано:

    Можно просто копировать команды со страницы документации, в окне консоли вверху есть стандартная кнопочка "Вставить". А вот точка в записи команд имеет значение, это ссылка на текущую папку!

    Ну и, конечно, для другой версии Studio будет другое указание компилятора, узнать своё можно командой

    Нужный генератор будет помечен в списке "звёздочкой".

    Теперь проект можно открывать в Studio и работать с ним, все нужные файлы есть в папке d:\temp\primesieve-master

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

    • Меню Проект - Свойства, слева выбираем Свойства конфигурации, C/C++, Общие, раскрываем поле "Дополнительные каталоги включаемых файлов", говорим "Изменить" и показываем на папку D:\Temp\primesieve-master\include . В вашем проекте, как правило, тоже будет вложенная папка include .
    • В том же окне выбираем Компоновщик - Общие - Дополнительные каталоги библиотек, "Изменить" и добавляем путь D:\Temp\primesieve-master\Release . Этого может оказаться мало, у вашего проекта и внешнего должны быть выбраны одинаковые конфигурации решения. Так как я выбрал Release для внешнего проекта, то и в своём проекте в списке "Конфигурации решения" (на стандартной панели инструментов) указал Release и платформу x64. Можно было работать и с Debug, но тогда и внешний проект компилируем как Debug и потом выбираем путь D:\Temp\primesieve-master\Debug .
    • В списке C/C++ - Создание кода - Библиотека времени выполнения выбрал Многопоточный DLL (/MD), иначе будет "LNK2038: обнаружено несоответствие для 'RuntimeLibrary': значение 'MT_StaticRelease' не соответствует значению 'MD_DynamicRelease' в file.obj".
    • Сам файл библиотеки, как правило имеющий тип .lib , тоже нужно прописать. Всё в том же окне свойства проекта выбираем список Компоновщик - Ввод, раскрываем список "Дополнительные зависимости", жмём "Изменить" и указываем в поле ввода имя файла библиотеки primesieve.lib
    • На всякий случай, проверяем, что у нас в списке Компоновщик - Система - Подсистема, у меня там просто Консоль (/SUBSYSTEM:CONSOLE) , для других типов проектов может понадобиться изменение и этой настройки.

    После этого у меня всё заработало.

    Ну а конкретная задача, на которой я проверял библиотеку - печать самых длинных цепочек последовательных простых чисел, в которых разница между соседними значениями строго возрастает или строго убывает, предел счёта равен 1000000, вот сама программа:

    Ответы вышли такие:

    За счёт хорошо оптимизированного кода библиотеки считается всё мгновенно.

    В наше время open source проекты все популярнее. На площадках открытых проектов, например, на github можно найти множество полезных программ, но они не всегда имеют исполняемые файлы ("exe"), поэтому я постараюсь рассказать о том, как можно собрать самостоятельно C/C++ программу, из исходников, написанную на Microsoft Visual Studio.

    Первым делом нам необходимо загрузить онлайн установщик Microsoft Visual Studio, с официального сайта. Для компиляции С/С++ проектов нет необходимости во всех пакетах и можно выбрать только те, которые нам необходимы.

    Установщик загрузит необходимые пакеты из интернета и установит их.

    После установки Visual Studio можно убедиться, что всё работает создав тестовый проект и скомпилировав его. Для этого нажмите в меню "Файл" → "Создать" → "Проект. "

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

    • Консольное приложение;
    • Классическое приложение;
    • Библиотеку динамической компоновки (dll);
    • Статическую библиотеку;

    В нашем случае для быстрой проверки подойдет консольное приложение, выбираем название и папку проекта , после чего жмём кнопку "ОК" и создается наша программа.

    После этого остается остается лишь скомпилировать её, для этого нужно выбрать в меню "Сборка" и нажать на пункт "Собрать решение".

    Далее наш проект скомпилируется и в папке проекта появится наш тестовый исполняемый файл ("exe").

    Если всё работает как надо, то можно приступать к сборке какого-нибудь другого открытого проекта с github или другого хостинга проектов.

    Первым делом нам нужно загрузить исходники проекта. На площадке github это делается довольно просто, жмем на кнопку "Code" и "Download ZIP". После чего нужно распаковать его и можно приступать к сборке.

    Ищем файл с расширением "<название_проекта>.vcxproj" и запускаем его. Перед нами появится диалог в котором нам предложат обновить SDK проекта (набор библиотек для разработки, которые Microsoft периодически обновляет) и набор инструментов, жмём обновить.

    Теперь наш проект можно собрать, но до сборки необходимо выбрать разрядность проекта (например, для 32 битной системы или 64 битной), а также тип сборки (отладочный режим - debug или release).

    Выбираем 64 битную систему и тип сборки релиз, после чего компилируем проект. Как и ранее нужно выбрать в меню "Сборка" и нажать на пункт "Собрать решение".

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

    Бывает, что проект использует сторонние библиотеки, для этого их нужно загрузить отдельно и положить в папку. Узнать путь или изменить его можно в свойстве проекта, в разделе "С/C++" → "Общие" → "Дополнительные каталоги включаемых файлов".

    Бывает, что SDK или набор инструментов, в свойстве проекта не изменяется в диалоге, чтобы изменить их нужно записать номер SDK, закрыть Visual Studio и вручную, блокнотом изменить этот номер в файле проекта "<название_проекта>.vcxproj".

    При возникновении других проблем можно попробовать их загуглить, возможно, что кто-то уже сталкивался с ними и решил их.

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