Правильный способ связать статические библиотеки с DLL
Мой проект строится через несколько статических библиотек, которые должны быть связаны с основной библиотекой DLL, и в результате получают одну DLL.
С помощью __declspec(dllexport)
Атрибут не приводит к появлению в dll указанных функций статических библиотек, библиотеки вообще не связаны с dll.
Затем я попытался собрать каждую библиотеку как общую для получения имен имен экспортируемых функций и создал на их основе файл.def. Использование файла.def приводит к результату.
Должен
__declspec(dllexport)
а также.def-file
действовать одинаково в моем случае?Можно ли сгенерировать файл.def из источников? Поскольку у меня есть код на C++, я не могу самостоятельно написать файл.def из-за искажения и классов присутствия в API, описанный выше подход с временными сгенерированными dll несовместим с производством.
Обновить
Я хотел бы подробно объяснить структуру моего проекта. Решение состоит из нескольких проектов (модулей).
+
|
+-+ static_lib1
| +
| +--+ src
|
+-+ static_lib2
| +
| +--+ src
|
+-+ dynamic_lib (linked with static_lib1 and static_lib2)
+
+--+ src
Каждый подпроект слабо зависит от других, давайте предположим, что они не связаны для ясности. Каждый модуль имеет собственный открытый интерфейс. Я хочу, чтобы все модули были единой динамической библиотекой, поэтому мой артефакт dynamic_lib.dll
, но на самом деле статические библиотеки не связаны с ним.
2 ответа
Статические библиотеки не должны содержать никаких __declspec
или же __attribute((dll...))
вещи. Это не более чем несколько объектных файлов (обычно *.obj
или же *.o
), составленный в один файл.
Все, что вам нужно сделать, чтобы использовать такую библиотеку (либо в .exe
или же .dll
) состоит в том, чтобы включить правильные заголовки и связать их - с Visual Studio это довольно просто.
Прежде всего, вам нужно знать 1) где находятся ваши статические библиотеки и 2) их точные имена. Перейти к свойствам проекта, а затем General
, Target name
содержит имя для выходного файла, в то время как Output directory
указывает в какой папке ваш .lib
будет размещен.
Примечание: этот путь может отличаться для каждого проекта! Для многопроектного решения я всегда устанавливаю общий путь, чтобы избежать проблем с конфигурацией.
Теперь перейдите к свойствам проекта, который будет использовать эту библиотеку (ссылка с ней). Идти к Linker
-> Input
а затем добавьте имя вашего .lib
в Additional dependencies
(записи разделяются точкой с запятой):
Вам нужно добавить все библиотеки, с которыми вы хотите связать. Также необходимо добавить папку, в которой эти библиотеки находятся. Linker
-> General
-> Additional library directories
, Я упал .lib
s размещены в одном месте - хорошо, в противном случае скопируйте их в общую папку или добавьте несколько записей в Additional library directories
список.
И последнее - помните, что вам также нужно включать заголовки с объявлениями функций и объектов, которые вы хотите использовать. Базовая вещь, я знаю, но должна быть упомянута.
ОБНОВИТЬ
неразрешенный внешний при попытке использовать библиотеку dll во внешних проектах
Ваша проблема не связана со ссылками вообще. Дело в том, что вы неправильно поняли, что именно делает ссылка на статическую библиотеку.
Я предполагаю, что функции, указанные как неразрешенные, не используются DLL
, право? Но вы ожидаете, что они будут внутри, верно?
Когда ваш DLL
ссылается на внешний контент (например, функцию или переменную), он разрешается во время связывания - вместе со всеми зависимостями. Но это все. Если в вашей статической библиотеке есть функция с именем print_sample_string()
, но ваш DLL
не использует его, он не будет прикреплен к DLL
образ. Подумайте об этом внимательно - почему это должно быть?
Еще больше - функции, которые не являются dllexport
Редактирование явно не будет видно в любом случае. Функции по умолчанию имеют внешнее хранилище - так что в основном они являются частными DLL
содержание.
Таким образом, чтобы ответить на ваш вопрос напрямую - если вам нужно использовать функции / переменные из static_lib1.lib
прикрепите его к клиентскому приложению - так же, как вы сейчас присоединяете его к dynamic_lib
, Другого пути нет. (*)
(*) По правде говоря - есть. Вы можете создать промежуточную функцию в DLL
, который экспортируется и вызывает нужную функцию внутри:
Где-то в dynamic_lib
:
DLL_EXP_IMP long CallFunctionFromA_Lib()
{
return some_function(); //this function is from static_lib1.lib
}
Где-то в .exe
:
long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib
Я не могу себе представить, однако, почему вы хотите сделать это, а не просто ссылку A.lib
и использовать его напрямую.