Visual studio поиск dll
В Visual Studio 2010 под VC++ Directories > Executable Directories я указал путь к glew32d.dll . Однако, когда я запускаю исполняемый файл, он все еще жалуется.
С другой стороны, если я копирую DLL в локальную папку и запускаю исполняемый файл, то он не жалуется.
Указание пути к DLL файлу в настройках вашего проекта не гарантирует, что ваше приложение будет найти DLL во время выполнения. Вы только сказали Visual Studio, как найти нужные ему файлы. У этого ничего нет. делать то, как программа находит то, что ей нужно, после ее создания.
Размещение DLL файла в той же папке, что и исполняемый файл, безусловно, является самым простым решением. Это путь поиска по умолчанию для зависимостей, поэтому вам не нужно ничего делать, если вы идете по этому маршруту.
Чтобы избежать необходимости делать это вручную каждый раз, вы можете создать событие Post-Build для своего проекта, чтобы автоматически скопирует DLL в соответствующий каталог после завершения сборки.
В качестве альтернативы вы можете развернуть DLL в Windows бок о бок кеш и добавить манифест в ваше приложение, которое указывает местоположение.
У меня возникла одна и та же проблема с той же самой библиотекой lib, которая находила решение здесь SO:
Поиск в MSDN для "Как установить переменные среды для проектов". (Это проект > Свойствa > Свойства конфигурации > Отладка Свойства "Окружающая среда" и "Слияние окружающей среды" для тех, кто находится в спешка.)
Синтаксис NAME = VALUE и макросы могут использоваться (например, $(OutDir)).
Например, чтобы добавить C:\Windows\Temp к PATH:
Аналогично, добавьте $(TargetDir)\DLLS в PATH:
Чтобы добавить к Олегу ответ:
* На самом деле я не знаю, использует ли макрос $(ExecutablePath) параметр "Исполняемые каталоги проекта" или глобальные страницы "Выполняемые каталоги свойств". Поскольку у меня есть все мои библиотеки, которые я часто использую, настроенные через страницы свойств, эти каталоги отображаются как значения по умолчанию для любых новых проектов, которые я создаю.
Доброго времени суток!
Есть проект C++ в VIsual Studio. В нем есть несколько DLL. Подключаются они неявно через LIB. Сейчас все DLL лежат в корне собираемого проекта (рядом с exe) и все прекрасно работает. Но есть необходимость перенести все DLL'ки в отдельную директорию (например пусть будет libs).
Вопрос, как это сделать? Как добавить директории поиска DLL или как прописать ссылки на эти самые DLL?
Я нашел только один способ - задать директории с DLL'ками через Свойства проекта -> Отладка. Но проблема в том, что все это работает только для запуска программы из среды VS. Если просто скомпилить EXE и запустить его, DLL все равно не находит.
Способ интересный, но будет работать только если DLL грузится на ходу, через LoadLibrary. Для обычной линковки с DLL (когда загрузчик загружает сам, ПЕРЕД тем как какая-либо инструкция из EXE будет выполнена) не подойдёт.
Вам необходимо добавить директории в переменную среды PATH. Это основной способ заставить загрузчик находить их помимо расположения рядом с EXE.
Как добавить эти директории - это другой вопрос. Конкретное решение зависит от того, в какой среде вам это нужно и какие у вас ограничения. Например, Конан умеет создавать т.н. "среду для запуска" (run environment) и создаёт специальные батники, где прописывает за вас пути к DLL-кам в пакетах. Эти батники могут "активировать" среду, прописав всё что нужно в PATH (пути к нужным DLL), в результате чего EXE-шник, использующий их, сможет их найти (точнее, системный загрузчик сможет найти), и "деактивировать" среду, чтобы вернуть PATH в исходное состояние. Это просто вам для примера решение, может быть вам понравится идея и вы сделаете такие же батники для запуска на машине разработчика или юзера.
В качестве примера мы рассмотрим подключение библиотеки SDL к нашему проекту в Visual Studio 2017 (работать будет и с более новыми версиями Visual Studio).
Шаг №1: Создаем папку для хранения библиотеки
Создаем папку Libs на диске C ( C:\Libs ).
Шаг №2: Скачиваем и устанавливаем библиотеку
Шаг №3: Указываем путь к заголовочным файлам библиотеки
Открываем свой любой проект в Visual Studio или создаем новый, переходим в "Обозреватель решений" > кликаем правой кнопкой мыши (ПКМ) по названию нашего проекта > "Свойства" :
В "Свойства конфигурации" ищем вкладку "С/С++" > "Общие" . Затем выбираем пункт "Дополнительные каталоги включаемых файлов" > нажимаем на стрелочку в конце > "Изменить" :
В появившемся окне кликаем на иконку с изображением папки, а затем на появившееся троеточие:
Заголовочные файлы находятся в папке include внутри нашей библиотеки, поэтому переходим в нее ( C:\Libs\SDL2-2.0.9\include ) и нажимаем "Выбор папки" , а затем "ОК" :
Шаг №4: Указываем путь к файлам с реализацией библиотеки
Переходим на вкладку "Компоновщик" > "Общие" . Ищем пункт "Дополнительные каталоги библиотек" > нажимаем на стрелочку в конце > "Изменить" :
Опять же, нажимаем на иконку с папкой, а затем на появившееся троеточие. Нам нужно указать следующий путь: C:\Libs\SDL2-2.0.9\lib\x86 . Будьте внимательны, в папке lib находятся две папки: x64 и x86 . Даже если у вас Windows разрядности x64, указывать нужно папку x86 . Затем "Выбор папки" и "ОК" :
После этого переходим в "Компоновщик" > "Ввод" . Затем "Дополнительные зависимости" > нажимаем на стрелочку в конце > "Изменить" :
В появившемся текстовом блоке вставляем:
Затем переходим в "Компоновщик" > "Система" . После этого "Подсистема" > нажимаем на стрелочку вниз > выбираем "Консоль (/SUBSYSTEM:CONSOLE)" > "Применить" > "ОК" :
Шаг №5: Копируем dll-ку в папку с проектом
Переходим в папку x86 ( C:\Libs\SDL2-2.0.9\lib\x86 ), копируем SDL2.dll и вставляем в папку с вашим проектом в Visual Studio. Чтобы просмотреть папку вашего проекта в Visual Studio, нажмите ПКМ по названию вашего проекта > "Открыть содержащую папку" :
Затем вставляем скопированный файл (SDL2.dll) в папку с проектом (где находится рабочий файл .cpp):
Шаг №6: Тестируем
Теперь, чтобы проверить, всё ли верно мы сделали — копируем и запускаем следующий код:
Рассмотрен по шагам процесс создания в Visual Studio файла динамически загружаемой библиотеки *.dll и методы вызова функций из неё. Все описанное далее делается на примере среды разработки Visual Studio 2003 Version 7.1.3088, но также подходит и к Visual Studio 2005. Для простоты папки создаваемых проектов будут находиться в директории C:\VSPROJ\.
[Создание библиотеки DLL]
1. File -> New -> Project, в дереве Project Types: выбираем Visual C++ Projects -> Win32, в окошке Templates: выбираем Win32 Console Project. В поле Name: вводим имя проекта для DLL, например MyDLL, в поле ввода Location: выбираем путь C:\VSPROJ (можно воспользоваться кнопкой Browse. ). Жмем ОК.
2. Появится окошко мастера настройки свойств проекта Win32 Application Wizard - MyDLL. Щелкаем на Application Settings, Application type: выбираем DLL, в Additional options: ставим галочку Empty project, жмем Finish.
3. Создадим заголовочный файл для модуля наших функций в создаваемой DLL. В дереве браузера проекта выбираем Header Files -> Add -> Add New Item. в дереве Categories: выбираем Visual C++ -> Code, в шаблонах Templates: выбираем Header File (.h). В поле Name: вводим любое имя файла, например mydllmodule, жмем Open.
namespace dllfuncs
class DummyClass
public :
// Делаем бип
static __declspec(dllexport) void ShortBeep ( void );
Вариант без использования классов:
__declspec(dllexport) void ShortBeep ( void );
__declspec(dllexport) void Msg ( char * msgstr);
4. Создадим файл для модуля наших функций в создаваемой DLL, в котором будет сам код функций. В дереве браузера проекта выбираем Source Files -> Add -> Add New Item. в дереве Categories: выбираем Visual C++ -> Code, в шаблонах Templates: выбираем C++ File (.cpp). В поле Name: вводим то же самое имя файла, которое вводили на шаге 3 - mydllmodule, жмем Open.
Создастся новый файл, к котором будет код функций, добавляемых в файл DLL. Вводим в него следующий текст:
using namespace std;
namespace dllfuncs
void DummyClass::ShortBeep( void )
Beep(1000,100); //частота 1000 Гц, длительность 100 мс
>
void DummyClass::Msg( char * msgstr)
MessageBox(NULL, msgstr, "Message from DLL" , MB_OK);
>
>
Вариант без использования классов:
using namespace std;
void ShortBeep( void )
Beep(1000,100); //частота 1000 Гц, длительность 100 мс
>
void Msg( char * msgstr)
MessageBox(NULL, msgstr, "Message from DLL" , MB_OK);
>
После всех этих действий появится папка C:\VSPROJ\MyDLL\, в которой будут находиться файлы mydllmodule.cpp и mydllmodule.h, а также конфигурационные файлы проекта MyDLL.
5. Чтобы наш проект скомпилировался в DLL, это должно быть настроено в свойствах проекта. Проверим настройки: MyDLL -> Properties. -> Configuration Properties -> General -> Configuration Type должно быть установлено в Dynamic Library (.dll). Жмем OK.
6. Теперь скомпилируем нашу библиотеку Build -> Build MyDLL. В папке C:\VSPROJ\MyDLL\Debug появятся два файла MyDLL.dll и MyDLL.lib. Первый файл MyDLL.dll - динамически загружаемая библиотека наших функций, она должна находится в папке исполняемого файла, который использует эти функции (см. [Создание приложения, которое использует функции из DLL]). Второй файл MyDLL.lib - статическая библиотека, которая может быть присоединена на этапе компиляции к приложению, использующему функции проекта MyDLL (см. [Создание приложения, которое использует функции из статической библиотеки lib]).
[Создание приложения, которое использует функции из загружаемой DLL]
Теперь создадим простую демонстрационную программу, которая будет вызвать функции из нашей DLL.
1. File -> New -> Project, в дереве Project Types: выбираем Visual C++ Projects -> Win32, в окошке Templates: выбираем Win32 Console Project. В поле Name: вводим имя проекта для приложения, использующего загрузку DLL, например DLLtest, в поле ввода Location: выбираем путь C:\VSPROJ (можно воспользоваться кнопкой Browse. ). Также выберем радиокнопку Add to Solution, это просто добавит в нашу группу проектов (в котором уже есть проект MyDLL) новый проект DLLtest. Жмем ОК.
2. Настроим свойства тестового приложения. Выберите тип приложения Console application и нажмите Finish.
После этого автоматически создастся папка C:\VSPROJ\DLLtest\, в ней появится файл DLLtest.cpp, и туда введется пустой код тела функции _tmain. В функцию _tmain мы впоследствии добавим вызовы функций из модуля MyDLL.
3. Нужно настроить в проекте DLLtest ссылки на загружаемую DLL. Щелкаем правой кнопкой на папку DLLtest в дереве Solution Explorer - DLLtest, выберем Add Reference. откроется окно выбора внешних ссылок на загружаемые библиотеки. На закладке Projects выберите MyDLL c:\Vsproj\MyDLL\ и нажмите кнопку Select, а затем OK. В проекте DLLtest в дереве проекта появится папка References и подпапка MyDLL, в которой с помощью Object Browser можно просмотреть функции из нашей библиотеки MyDLL.
Весь код для загрузки DLL и инициализации указателей на используемые функции будет сгенерирован автоматически в процессе компиляции приложения.
4. Вставим в приложение вызовы функций Msg и ShortBeep, для этого добавим в модуль DLLtest.cpp включаемый заголовок mydllmodule.h, и установим добавочные пути поиска файлов заголовков проекта DLLtest. Жмем правую кнопку на DLLtest -> выбираем Properties -> Configuration Properties -> C/C++ -> General -> Additional Include Directories -> $(ProjectDir)\..\MyDLL и жмем OK.
Добавим в модуль DLLtest.cpp вызовы функций ShortBeep и Msg, код модуля DLLtest.cpp получится следующий:
// DLLtest.cpp : здесь определена точка входа для консольного приложения.
//
using namespace std;
int _tmain( int argc, _TCHAR* argv[])
dllfuncs::DummyClass::ShortBeep();
dllfuncs::DummyClass::Msg( "Hello, world!" );
return 0;
>
Вариант без использования классов:
// DLLtest.cpp : Defines the entry point for the console application.
//
using namespace std;
int _tmain( int argc, _TCHAR* argv[])
ShortBeep();
Msg( "Hello, world!" );
return 0;
>
[Пути поиска библиотек DLL при запуске приложения]
При запуске приложения Windows выполняет поиск библиотек DLL в следующей последовательности:
1. Каталог, в котором находится исполняемый модуль текущего процесса.
2. Текущий каталог.
3. Системный каталог Windows (обычно это папка System32). Путь к этому каталогу извлекается с помощью функции GetSystemDirectory.
4. Каталог Windows. Путь к этому каталогу извлекается с помощью функции GetWindowsDirectory.
5. Каталоги, указанные в переменной среды PATH.
Примечание: переменная среды LIBPATH не используется.
[Ошибки в проектах с DLL]
1. <имя_программы> fatal error LNK1104: cannot open file 'путь_до_папки_проекта_DLL\Debug\имя_файла_библиотеки.lib', например:
DLLtest fatal error LNK1104: cannot open file '\Vsproj\MyDLL\Debug\MyDLL.lib'
Проблема решается, если положить в путь поиска нужную DLL (для нашего примера файл MyDLL.dll нужно положить в папку C:\VSPROJ\DLLtest\). Самое лучшее решение - настроить команду в Post-Build Event, которая будет автоматически выполнить копирование DLL в папку отладки программы, которая использует эту DLL. Настраивается Post-Build Event просто, процесс по шагам, на нашем примере проектов MyDLL и DLLtest (предполагается, что обе папки проектов находятся на одном уровне в файловой системе, и входят в один Solution среды разработки Visual Studio, см. [3]):
1. Сначала нужно настроить порядок компиляции проектов в Solution. DLL должна компилироваться первой. Порядок компиляции настраивается через свойства Solution, контекстное меню Project Build Order.
Порядок проектов в списке можно поменять с помощью закладки Dependencies, которая определяет, какой проект от какого зависит. Первым в списке в нашем примере должен быть проект MyDLL.
2. Теперь осталось в проекте MyDLL настроить Post Build Event, копирующее результат компиляции - файл MyDLL.dll в папку Debug проекта DLLtest. Щелкаем правой кнопкой в Solution Explorer на проекте MyDLL, выбираем Properties -> Configuration Properties -> Build Events -> Post-Build Event -> вставляем в поле Command Line строку cmd /C copy /Y $(TargetPath) $(ProjectDir)\..\DLLtest\Debug\$(TargetFileName).
[Как отлаживать код DLL в Visual Studio]
В IDE есть приятная возможность отладки DLL по тексту исходного кода, однако это настраивается не слишком очевидно. Процесс по шагам (на нашем примере проектов MyDLL и DLLtest).
1. Сначала нужно задать при отладке стартовым приложением в Solution проект с DLL.
2. Нужно убедиться, что оба проекта MyDLL и DLLtest скомпилированы в конфигурации для отладки Debug.
3. Нужно настроить в свойствах проекта MyDLL запуск внешнего приложения, вызывающего нашу DLL. Щелкаем правой кнопкой в Solution Explorer на проекте MyDLL, выбираем Properties -> Configuration Properties -> Debugging -> в поле Command вводим строку $(ProjectDir)\..\DLLtest\Debug\DLLtest.exe.
Теперь можно ставить точки останова в исходном коде DLL, и отлаживать его, как обычный код. Если у Вас не работает отладка по коду DLL, то возможно, что-то не так с символами отладки (отладочной информацией). Если отладочная информация по коду DLL недоступна, то точки останова в DLL будут в виде коричневых кружков со знаками вопроса. Разобраться с проблемой загрузки символов может помочь просмотр модулей Debug -> Windows -> Modules. На скриншоте показана как раз такая проблема с отладкой.
Читайте также: