Как добавить dll в проект visual studio c
Использование DLL в программе на Visual C++
Многие знают, что существует два основных способа подключить DLL к программе - явный и неявный.
При неявном подключении (implicit linking) линкеру передается библиотека импорта (обычно имеет расширение lib), содержащая список переменных и функций DLL, которые могут использовать приложения. Обнаружив, что программа обращается хотя бы к одной из них, линкер добавляет в целевой exe-файл таблицу импорта . Таблица импорта содержит список всех DLL, которые использует программа, с указанием конкретных переменных и функций, к которым она обращается. Позже, когда exe-файл будет запущен, загрузчик проецирует все DLL, перечисленные в таблице импорта, на адресное пространство процесса; в случае неудачи весь процесс немедленно завершается.
При явном подключении (explicit linking) приложение вызывает функцию LoadLibrary, чтобы загрузить DLL, затем использует функцию GetProcAddress, чтобы получить указатели на требуемые функции (или переменные), а по окончании работы с ними вызывает FreeLibrary, чтобы выгрузить библиотеку и освободить занимаемые ею ресурсы.
Каждый из способов имеет свои достоинства и недостатки. В случае неявного подключения все библиотеки, используемые приложением, загружаются в момент его запуска и остаются в памяти до его завершения (даже если другие запущенные приложения их не используют). Это может привести к нерациональному расходу памяти, а также заметно увеличить время загрузки приложения, если оно использует очень много различных библиотек. Кроме того, если хотя бы одна из неявно подключаемых библиотек отсутствует, работа приложения будет немедленно завершена. Явный метод лишен этих недостатков, но делает программирование более неудобным, поскольку требуется следить за своевременными вызовами LoadLibrary и соответствующими им вызовами FreeLibrary, а также получать адрес каждой функции через вызов GetProcAddress.
Теперь рассмотрим, как каждый из перечисленных методов используется на практике. Для этого будем считать, что у нас есть библиотека MyDll.dll, которая экспортирует переменную Var, функцию Function и класс Class. Их объявления содержатся в заголовочном файле MyDll.h, который выглядит следующим образом:
Кроме того, будем считать, что библиотека импорта содержится в файле MyDll.lib.
Неявное подключение
Это наиболее простой метод подключения DLL к нашей программе. Все, что нам нужно - это передать линкеру имя библиотеки импорта, чтобы он использовал ее в процессе сборки. Сделать это можно различными способами.
Теперь можно использовать в программе любые переменные, функции и классы, содержащиеся в DLL, как если бы они находились в статической библиотеке. Например:
Явное подключение
Загрузка DLL
Как уже говорилось ранее, при явном подключении DLL программист должен сам позаботиться о загрузке библиотеки перед ее использованием. Для этого используется функция LoadLibrary, которая получает имя библиотеки и возвращает ее дескриптор. Дескриптор необходимо сохранить в переменной, так как он будет использоваться всеми остальными функциями, предназначенными для работы с DLL.
В нашем примере загрузка DLL выглядит так.
Вызов функций
После того как библиотека загружена, адрес любой из содержащихся в ней функций можно получить с помощью GetProcAddress, которой необходимо передать дескриптор библиотеки и имя функции. Затем функцию из DLL можно вызывать, как обычно. Например:
Обратите внимание на приведение указателя к ссылке на тип FARPROC. FARPROC - это указатель на функцию, которая не принимает параметров и возвращает int. Именно такой указатель возвращает функция GetProcAddress. Приведение типа необходимо, чтобы умиротворить компилятор, который строго следит за соответствием типов параметров оператора присваивания. Альтернативный подход заключается в использовании оператора typedef с последующим приведением значения, возвращаемого GetProcAddress, к указателю на функцию с нужным прототипом.
Доступ к переменным
Хотя это не всегда очевидно из документации, получить указатель на переменную из DLL можно, используя все ту же функцию GetProcAddress. В нашем примере это выглядит так.
Использование классов
Сразу замечу, что в общем случае не рекомендуется размещать классы в библиотеках, подключаемых явно. Приемлемым можно считать только подход, который исповедует COM, при котором объекты класса создаются и разрушаются внутри DLL (для этого используются экспортируемые глобальные функции), а сам класс содержит исключительно виртуальные методы.
Однако предположим, что у нас нет доступа к исходным кодам библиотеки, содержащей класс, а использование других типов подключения DLL по каким-то причинам невозможно. Классом удастся воспользоваться и в этом случае, но для достижения цели придется проделать дополнительную работу.
Сначала задумаемся, почему объекты класса из явно подключаемой библиотеки нельзя использовать, как обычно. Дело в том, что при создании объекта класса компилятор генерирует вызов его конструктора. Но линкер не может разрешить этот вызов, поскольку адрес конструктора будет известен только в процессе выполнения программы. В результате сборка программы закончится неудачно. Такая же проблема возникает при вызове невиртуальных методов класса. С другой стороны, вызов виртуальных методов возможен, так как он осуществляется через таблицу виртуальных функций (vtable). Так, следующий фрагмент откомпилируется и слинкуется нормально (хотя, конечно, вызовет ошибку в процессе выполнения):
Приведенные выше рассуждения подсказывают решение проблемы. Коль скоро неявный вызов конструктра невозможен, мы можем вызвать его вручную, предварительно получив его адрес и выделив память под объект. Затем можно вызывать невиртуальные методы, получая их адреса с помощью GetProcAddress. Виртуальные методы можно вызывать, как обычно. Кроме того, необходимо не забыть вручную вызвать деструктор объекта, прежде чем выделенная для него память будет освобождена.
Продемонстрирую все сказанное на примере. Сначала мы выделяем память для объекта и вызываем для него конструктор. Память можно выделить как на стеке, так и в куче (с помощью оператора new). Рассмотрим оба варианта.
Обратите внимание на использование операторов .* и ->* для вызова функции-члена класса по указателю на нее. Этими операторами мы будем пользоваться и дальше.
ПРИМЕЧАНИЕ
Как правило, имена функций, экспортируемых из DLL, искажаются линкером. Поэтому вместо понятного имени, такого как "Constructor", получается совершенно нечитабельное имя вида "??0Class@@QAE@XZ". В рассматриваемом примере я назначил переменным и функциям нормальные имена при помощи def-файла следующего содержания:
Невиртуальные методы класса вызываются так же, как и конструктор, например:
Виртуальные методы вызываются непосредственно (как это делается для обычных классов). Хотя DLL и экспортирует их, явно получать их адреса с помощью GetProcAddress не требуется. Отсюда следует вывод: если все методы класса являются виртуальными, использование объектов класса из явно подключаемой библиотеки практически ничем не отличается от использования объектов любого другого класса. Разница только в том, что конструктор и деструктор для таких объектов придется вызывать вручную.
В нашем примере виртуальная функция вызывается так.
После того, как работа с объектом завершена, его нужно уничтожить, вызвав для него деструктор. Если объект был создан на стеке, деструктор необходимо вызвать до его выхода из области видимости, иначе возможны неприятные последствия (например, утечки памяти). Если объект был распределен при помощи new, его необходимо уничтожить перед вызовом delete. В нашем примере это выглядит так.
До сих пор я ничего не говорил о статических переменных и функциях класса. Дело в том, что они практически ни чем не отличаются от обычных функций и переменных. Поэтому к ним можно обращаться, используя уже известные нам методы. Например:
Выгрузка библиотеки
После того, как работа с библиотекой закончена, ее можно выгрузить, чтобы она не занимала системные ресурсы. Для этого используется функция FreeLibrary, которой следует передать дескриптор освобождаемой библиотеки. В нашем примере это выглядит так.
Отложенная загрузка
Использование отложенной загрузки
Вот и все. Теперь можно использовать функции и классы DLL прозрачно, как и в случае с неявным подключением. Единственная проблема возникает с переменными: их невозможно использовать напрямую. Дело в том, что при обращении к одной из функций в DLL мы на самом деле вызываем функцию __delayLoadHelper, которая и выполняет загрузку DLL (если она еще не загружена), затем получает адрес функции с помощью GetProcAddress и перенаправляет все последующие вызовы функции по этому адресу. Но при обращении к переменной вызова функции не происходит, а значит использовать __delayLoadHelper не удается.
Проблема решается путем явного использования GetProcAddress при работе с переменными. Если DLL еще не загружена, ее придется загрузить явно с помощью LoadLibrary. Но если мы уже обращались к ее функциям и точно знаем, что она находится в памяти, мы можем получить ее дескриптор с помощью функции GetModuleHandle, которой необходимо передать имя DLL. В нашем примере это выглядит так.
Выгрузка библиотеки
Итак, мы установили, что при использовании отложенной загрузки DLL грузится в память, когда происходит обращение к одной из ее функций. Но в последствии нам может потребоваться выгрузить ее, чтобы не занимать зря системные ресурсы. Специально для этого предназначена функция __FUnloadDelayLoadedDLL, объявленная в файле Delayimp.h. Если вы планируете использовать ее, вам нужно задать еще один ключ линкера - /DELAY:UNLOAD. Например:
Имя, которое вы передаете функции __FUnloadDelayLoadedDLL, должно в точности соответствовать имени, заданному в ключе /DELAYLOAD. Если, к примеру, передать ей "MYLIB.DLL" или "mylib.dll", библиотека останется в памяти.
ПРЕДУПРЕЖДЕНИЕ
Не используйте FreeLibrary, чтобы выгрузить DLL с отложенной загрузкой.
Обработка исключений
Как я уже говорил, в случае ошибки функция __delayLoadHelper возбуждает исключение. Если нужная DLL не обнаружена, возбуждается исключение с кодом VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND). Если в DLL не обнаружена требуемая функция, исключение будет иметь код VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND).
ПРИМЕЧАНИЕ
VcppException - это макрос, который используется для формирования кода ошибки в подсистеме Visual C++. Первый параметр задает "степень серьезности" ошибки, а второй - код исключения.
И то, и другое исключение можно обработать, используя механизм структурной обработки исключений. Для этого нужно написать фильтр , реагирующий на приведенные коды исключения, а также обработчик исключения. В простейшем случае они могут выглядеть так.
Написанный вами фильтр исключений может также получить дополнительную информацию с помощью функции GetExceptionInformation. Эта функция возвращает указатель на структуру EXCEPTION_POINTERS. В ней содержится поле ExceptionRecord - указатель на структуру EXCEPTION_RECORD. А структура EXCEPTION_RECORD в свою очередь содержит поле ExceptionInformation[0], в которое __delayLoadHelper помещает указатель на структуру DelayLoadInfo, содержащую дополнительную информацию. Эта структура объявлена следующим образом (файл Delayimp.h).
В частности, вы можете извлечь из нее имя DLL (поле szDll), а также имя или порядковый номер функции, вызов которой привел к исключению (поле dlp).
Функции-ловушки
Функции-ловушки должны иметь следующий прототип:
Первый параметр функции содержит код уведомления или ошибки, второй - указатель на уже знакомую нам структуру DelayLoadInfo. Все возможные коды уведомления описаны в файле Delayimp.h при помощи следующего перечисления:
В качестве примера приведу текст функции-ловушки, которая подменяет вызов функции SomeFunc на вызов функции YetAnotherFunc.
Ошибка в Delayimp.lib
И последнее замечание. Иногда при попытке слинковать программу с библиотекой Delayimp.lib линкер выдает ошибку Access Violation и аварийно завершается. Это связано с тем, что в некоторых дистрибутивах Visual C++ распространяется поврежденный файл Delayimp.lib. Если у вас возникла такая проблема, загрузите корректную версию файла здесь и скопируйте его в каталог %Visual Studio Folder%\Vc98\Lib\.
Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
Использование скачанных библиотек с помощью vcpkg
Если вы хотите использовать скачанную библиотеку с помощью диспетчера пакетов vcpkg, то приведенные ниже инструкции можно пропустить. дополнительные сведения см. в разделе vcpkg. io.
Использование статических библиотек
Если проект статической библиотеки был создан в том же решении:
Если статическая библиотека не входит в состав решения:
- Щелкните правой кнопкой мыши узел проекта приложения в обозревателе решений и выберите Свойства.
- На странице свойств Каталоги VC++ добавьте в раздел Пути библиотек путь к каталогу, который содержит LIB-файл. Затем добавьте в раздел Включаемые каталоги путь к файлам заголовков библиотеки.
- На странице входное свойство компоновщика > добавьте имя файла lib в Дополнительные зависимости.
Библиотеки динамической компоновки
Если библиотека DLL была собрана в рамках того же решения, что и приложение, выполните те же действия, что и для статической библиотеки.
Если библиотека DLL не входит в состав решения приложения, вам потребуются DLL-файл, заголовки с прототипами для экспортируемых функций и классов, а также LIB-файл, содержащий необходимую для компоновки информацию.
- Скопируйте DLL-файл в папку выходных данных проекта или другую папку, которая задана в качестве стандартной для поиска библиотек DLL в Windows. Дополнительные сведения см. в статье Порядок поиска библиотек динамической компоновки.
- Выполните шаги с 1 по 3 для статических библиотек, чтобы задать пути к заголовкам и LIB-файлу.
COM-объекты
Свойства ссылки
Каждый тип ссылки имеет свойства. Свойства можно просмотреть, выбрав ссылку в обозревателе решений и нажав клавиши Alt + ВВОД. Также можно щелкнуть ссылку правой кнопкой мыши и выбрать пункт Свойства. Одни свойства доступны только для чтения, другие можно изменять. Тем не менее обычно эти свойства не требуется изменять вручную.
Свойства ссылки ActiveX
Свойства ссылки ActiveX доступны только для компонентов COM. Данные свойства отображаются только тогда, когда в панели Ссылки выбран компонент COM. Эти свойства нельзя изменить.
Управление полным путем
Отображает путь к каталогу элемента управления, на который указывает ссылка.
GUID элемента управления
Отображает GUID для элемента управления ActiveX.
Версия элемента управления
Отображает версию элемента управления ActiveX, на который указывает ссылка.
Имя библиотеки типов
Отображает имя библиотеки типов, на которую указывает ссылка.
Средство программы-оболочки
Отображает средство, которое используется для создания сборки взаимодействия из указанной библиотеки COM или элемента управления ActiveX.
Свойства ссылки на сборку (C++/CLI)
Относительный путь
Отображает относительный путь от каталога проекта к сборке, на которую указывает ссылка.
Свойства сборки
Следующие свойства доступны для различных типов ссылок. Они позволяют задавать способ построения со ссылками.
Копировать локальные
Указывает, следует ли автоматически копировать сборку, на которую указывает ссылка, в целевое расположение во время сборки.
Копировать локальные вспомогательные сборки (C++/CLI)
Указывает, следует ли автоматически копировать вспомогательные сборки ссылочной сборки в целевое расположение во время сборки. Используется, только если для параметра Копировать локальные задано значение true .
Выходные данные ссылочной сборки
Указывает, что эта сборка используется в процессе сборки. true означает, что эта сборка используется в командной строке компилятора во время выполнения сборки.
Свойства ссылок проектов на проекты
Следующие свойства определяют ссылку проекта на проект из проекта, выбранного в панели Ссылки, на другой проект в том же решении. Дополнительные сведения см. в статье Управление ссылками в проекте.
Компоновать зависимости библиотек
Если это свойство имеет значение True, система проектов установит в зависимом проекте связь с LIB-файлами, создаваемыми независимым проектом. Обычно устанавливается значение True.
Идентификатор проекта
Уникальный идентификатор независимого проекта. Значение свойства — это GUID внутренней системы, который невозможно изменить.
Использовать входные данные зависимостей библиотек
Если это свойство имеет значение False, система проектов не установит в зависимом проекте связь с OBJ-файлами для библиотеки, созданной независимым проектом. Таким образом, это значение отключает инкрементную компоновку. Обычно указывается значение False, так как при наличии множества независимых проектов сборка приложения может занять длительное время.
Имя сборки
Отображает имя сборки для сборки, на которую указывает ссылка.
Язык и региональные параметры
Отображает язык и региональные параметры выбранной ссылки.
Описание
Отображает описание выбранной ссылки.
Полный путь
Отображает путь к каталогу сборки, на которую указывает ссылка.
Удостоверение
Label
Отображает метку ссылки.
Name
Отображает имя ссылки.
Токен открытого ключа
Отображает токен открытого ключа для идентификации сборки, на которую указывает ссылка.
Строгое имя
true , если сборка, на которую указывает ссылка, имеет строгое имя. Сборка со строгим именем имеет уникальную версию.
Библиотека DLL (библиотека динамической компоновки) — это библиотека, содержащая код и данные, которые могут использоваться несколькими приложениями. Visual Studio можно использовать для создания, сборки, настройки и отладки библиотек DLL.
Создание библиотеки DLL
Создавать библиотеки DLL можно с помощью следующих шаблонов проектов Visual Studio.
Дополнительные сведения см. в разделе Методы отладки MFC.
Отладка библиотеки WCF аналогична отладке библиотеки классов. Дополнительные сведения см. в статье Элементы управления Windows Forms.
Обычно библиотека DLL вызывается из другого проекта. При отладке вызывающего проекта в зависимости от конфигурации библиотеки DLL можно выполнить шаг с заходом и отладить код библиотеки DLL.
Конфигурация отладки библиотеки DLL
При создании приложения на основе шаблона проекта Visual Studio Visual Studio автоматически создает требуемые параметры для конфигурации сборки отладки и выпуска. При необходимости эти параметры можно изменить. Дополнительные сведения см. в следующих статьях:
Установка DebuggableAttribute C++
Чтобы отладчик мог присоединиться к библиотеке DLL C++, код C++ должен добавлять DebuggableAttribute .
Установка DebuggableAttribute
В обозревателе решений выберите проект DLL C++ и щелкните значок Свойства либо щелкните проект правой кнопкой мыши и выберите пункт Свойства.
В области Свойства в разделе Компоновщик > Отладка выберите Да (/ASSEMBLYDEBUG) для свойства Отлаживаемая сборка.
Дополнительные сведения см. в статье /ASSEMBLYDEBUG.
Задание расположений файлов DLL C/C++
Для отладки внешней библиотеки DLL вызывающий проект должен находить библиотеку DLL, ее PDB-файл и любые другие файлы, необходимые библиотеке DLL. Вы можете создать пользовательскую задачу сборки, чтобы скопировать эти файлы в выходную папку \Debug, или скопировать файлы вручную.
Для проектов C/C++ можно задать расположения файлов заголовков и LIBD-файла на страницах свойств проекта, а не копировать их в выходную папку.
Задание расположений файла заголовка C/C и LIB-файла
В обозревателе решений выберите проект DLL C/C++ и щелкните значок Свойства либо щелкните проект правой кнопкой мыши и выберите пункт Свойства.
В верхней части области Свойства в разделе Конфигурация выберите Все конфигурации.
В разделе C/C++ > Общие > Дополнительные включаемые каталоги укажите папку с файлами заголовков.
В разделе Компоновщик > Общие > Дополнительные каталоги библиотек укажите папку с LIB-файлами.
В разделе Компоновщик > Ввод > Дополнительные зависимости укажите полный путь и имя файла для LIB-файлов.
Дополнительные сведения о параметрах проекта C++ см. в статье Справочник C++ по страницам свойств проекта Windows.
Сборка отладочной версии
Перед началом отладки обязательно создайте отладочную версию библиотеки DLL. Для отладки библиотеки DLL вызывающее приложение должно находить PDB-файл и любые другие файлы, необходимые библиотеке DLL.
Вы можете создать пользовательскую задачу сборки, чтобы скопировать эти файлы DLL в выходную папку \Debug, или скопировать файлы вручную.
Обязательно вызовите библиотеку DLL в правильном расположении. Это может показаться очевидным, но, если вызывающее приложение находит и загружает другую копию библиотеки DLL, отладчик никогда не достигнет заданных точек останова.
Отладка библиотека DLL
Библиотеку DLL нельзя запускать напрямую. Ее должно вызывать приложение, обычно это EXE-файл. Дополнительные сведения см. в статье Проекты Visual Studio — C++.
Чтобы отладить библиотеку DLL, можно начать отладку из вызывающего приложения или выполнить отладку из проекта DLL, указав вызывающее приложение. Можно также использовать окно "Интерпретация" отладчика для вычисления функций или методов DLL во время разработки без использования вызывающего приложения.
Дополнительные сведения см. в статье Первое знакомство с отладчиком.
Запуск отладки из вызывающего приложения
Вызывать библиотеку DLL могут следующие виды приложений.
- Приложение из проекта Visual Studio в том же или другом решении из библиотеки DLL.
- Существующее приложение, которое уже развернуто и работает на тестовом или рабочем компьютере.
- Программа расположена в Интернете и доступна по URL–адресу.
- Веб-приложение с веб-страницей, которая внедряет библиотеку DLL.
Выполнить отладку библиотеки DLL из вызывающего приложения можно следующими способами.
Откройте проект для вызывающего приложения и начните отладку, выбрав Отладка > Начать отладку или нажав клавишу F5.
Выполните присоединение к приложению, которое уже развернуто и работает на тестовом или рабочем компьютере. Используйте этот вариант для библиотек DLL на веб-сайтах или в веб-приложениях. Дополнительные сведения см. в разделе Практическое руководство. Присоединение к выполняемому процессу.
Перед запуском отладки этого вызывающего приложения нужно установить точку останова в DLL. См. статью Использование точек останова. При попадании в точку останова DLL можно пошагово проходить по коду, наблюдая действия в каждой строке. Дополнительные сведения см. в статье Навигация по коду с помощью отладчика.
Во время отладки в окне Модули можно проверить библиотеки DLL и EXE-файлы, загружаемые приложением. Чтобы открыть окно Модули, во время отладки выберите Отладка > Окна > Модули. Дополнительные сведения см. в разделе Практическое руководство. использовать окно модулей.
Использование окна "Интерпретация"
Окно Интерпретация можно использовать для вычисления функций или методов DLL во время разработки. Окно Интерпретация выполняет роль вызывающего приложения.
Окно Интерпретация можно использовать во время разработки с большинством типов проектов. Оно не поддерживается для SQL, веб-проектов или скриптов.
Например, чтобы протестировать метод с именем Test в классе Class1 , выполните следующие действия.
Откройте проект DLL, откройте окно Интерпретация, последовательно выбрав пункты Отладка > Окна > Интерпретация или нажав сочетание клавиш CTRL+ALT+I.
Предположим, что Test принимает один параметр int , вычислим Test с помощью окна Интерпретация :
Результат будет выведен в окне Интерпретация.
Можно продолжить отладку Test , установив в нем точку останова, а затем снова вычислив эту функцию.
Будет достигнута точка останова и можно будет пошагово пройти Test . После выполнения Test , отладчик вернется в режим разработки.
Отладка в смешанном режиме
Вы можете написать вызывающее приложение для библиотеки DLL в управляемом или машинном коде. Если собственное приложение вызывает управляемую библиотеку DLL и вы хотите выполнить отладку этих двух объектов, можно включить управляемые и машинные отладчики в свойствах проекта. Точный способ выполнения этой операции зависит от того, откуда будет начата отладка: из проекта DLL или из проекта вызывающего приложения. Дополнительные сведения см. в разделе Практическое руководство. Отладка в смешанном режиме.
Можно выполнить отладку собственной библиотеки DLL из управляемого вызывающего проекта. Дополнительные сведения см. в статье об отладке управляемого и машинного кода.
3. Если вы хотите добавить в проект свою или стороннюю библиотеку, то перейдите к пункту №7, если же вы хотите подключить сборку, входящую в состав FCL, тогда в меню Reference Manager выберите пункт Assemblies
4. Выберите подпункт Framework
5. В появившемся по центу списке выберите нужную вам сборку и нажмите кнопку OK.
6. В папке References должна появиться ссылка на добавленный вами файл.
7. Если вам требуется подключить в проект свою или чью-то скаченную библиотеку, то тогда, сначала, нажмите кнопку Browse
8. Откроется диалоговое окно. Перейдите в папку, которая содержит нужный вам dll файл, выберите его и нажмите кнопку Add
9. Выберите пункт Browse
10. Убедитесь, что добавленный файл выбран и нажмите кнопку OK
11. В папке References должна отобразиться ссылка на добавленный вами файл
Приносим извинения. Запрошенное содержимое было удалено. Вы будете автоматически перенаправлены через 1 секунду.
Лучший отвечающий
Вопрос
Сначала как обычно создаю библиотеку с функциями, обозначенными extern "C" _declspec(dllexport) ?
Затем включаю .h-файл библиотеки в проект Windows Forms.
Что затем? Установить свойство Linker->Additionals Dependencies, выбрав там свой lib-файл? Где он должен находиться, в какой папке? Где должна находиться моя dll? (Хотелось бы рядом с exe, как это сделать?)
Какие-то из этих шагов неправильные?
Ответы
> как сделать подключение через маршаллинг? А системные библиотеки user, kernel и т.д. каким образом подключаются?
из неуправляемых dll можно использовать функции, подключив их с помощью DllImportAttribute и extern
примерно так:
> Мне просто нужна библиотека без всяких классов, пусть управляемая, просто несколько функций. Я создаю ClassLibrary, ок. [. ] Затем второй разработчик должен взять мою библиотеку и как-то подключить её к своему проекту Windows Forms.
Все ответы
А есть примеры как сделать подключение через маршаллинг?
А системные библиотеки user, kernel и т.д. каким образом подключаются? Где для них маршаллинг прописан?
> как сделать подключение через маршаллинг? А системные библиотеки user, kernel и т.д. каким образом подключаются?
из неуправляемых dll можно использовать функции, подключив их с помощью DllImportAttribute и extern
примерно так:
Мне просто нужно создать библиотеку с функциями и подключить её к приложению Windows Form. Библиотеку без классов. только функции.
> Мне просто нужно создать библиотеку с функциями и подключить её к приложению Windows Form.
в Visual Studio создайте проект Windows Forms Application;
после этого добавьте новый проект: File - Add - New Project. - Class Library;
в Solution Explorer будут два проекта: WindowsFormsApplication1 и ClassLibrary1;
надо выделить проект WindowsFormsApplication1 и в контекстном меню выбрать: Add Reference. - ClassLibrary1
Посмотрите еще раз ответы Yatajga, они раскрывают суть вопроса. И также ответы Malobukv, в них приведены примеры.
Да, когда я заканчиваю задавать вопросы по теме, я всегда отмечаю как ответ, в том числе и Вас-). Как только разберусь с этой темой, обязательно помечу.
Мне просто нужна библиотека без всяких классов, пусть управляемая, просто несколько функций. Я создаю ClassLibrary, ок. Туда можно написать функции (наверное, можно ли. ) и классы (один с именем Class1 там уже есть). Я создаю эту библиотеку отдельно, а затем мне нужно передать её уже в виде готового файла .dll и файла заголовков .h другому разработчику. Всё. Мне не нужно объединять их в одном проекте.
Затем второй разработчик должен взять мою библиотеку и как-то подключить её к своему проекту Windows Forms. Где какие ссылки добавлять? На что ссылки? lib-файлы создаются в первом проекте, если поставить перед функцией (хотя бы одной) расширение extern "C" _declspec(dllexport).
У неё должен быть свой .lib файл? Как его создать при создании библиотеки, если нельзя (нельзя?) использовать extern "C" _declspec(dllexport)? Где он должен находится? Если сама библиотека находится в той же папке, что и .exe файл, где прописать путь к ней?
> Мне просто нужна библиотека без всяких классов, пусть управляемая, просто несколько функций. Я создаю ClassLibrary, ок. [. ] Затем второй разработчик должен взять мою библиотеку и как-то подключить её к своему проекту Windows Forms.
Создаю библиотеку, код на С++ примерно такой же. Для примера создал класс с функцией в нём и просто функцию. Компилирую, всё нормально.
Теперь копирую созданную dll в папку с проектом exe, щёлкаю правой кнопкой на имени проекта, выбираю References->Add New Reference, там выбираю свою dll, она появляется в списке рядом с System, System.Drawing и т.д.
Далее просто вызов в коде DllNamespace::MyFunction(); либо DllNamespace::MyClass::MyClFunction(); - для cлучая с классом всё работает.
Если же без класса просто функцию, выдаёт простую ошибку: MyFunction identifier not found. Если включить .h файл, то уже выдаст unresolved externals.
То есть таким способом можно создать библиотеку классов, а создать библиотеку с функциями без классов, да ещё чтобы подключать к проекту заголовочный файл, не получается. Файл exe не видит в библиотеке функции, только классы. А через заголовочный файл вообще непонятно как работать.
Да, в этом его недостаток. Майкрософт 10 лет навязывала всем Visual Basic, а когда этого не получилось, стала навязывать NET. Для простеньких задач он подходит отлично, программирование облегчает. Но как только требуется сделать что-то более сложное, так приходится тратить втрое больше сил, чтобы не только использовать старые проверенные технологии, но ещё и преодолевать трудности, связанные с ограничениями, которые прилепили в новых. Как пример - простейшее взаимодействие форм уже требует обращения к win32 SendMessage и т.д. Без win32 никак не обойтись, однако использование её превращается в головную боль. Сейчас знакомлюсь с технологией Windows Forms, откровенно разочарован. Очередной Бейсик.
Спасибо за ответы!
> простейшее взаимодействие форм уже требует обращения к win32 SendMessage и т.д. Без win32 никак не обойтись
Да, в этом его недостаток. Майкрософт 10 лет навязывала всем Visual Basic, а когда этого не получилось, стала навязывать NET. Для простеньких задач он подходит отлично, программирование облегчает. Но как только требуется сделать что-то более сложное, так приходится тратить втрое больше сил, чтобы не только использовать старые проверенные технологии, но ещё и преодолевать трудности, связанные с ограничениями, которые прилепили в новых. Как пример - простейшее взаимодействие форм уже требует обращения к win32 SendMessage и т.д. Без win32 никак не обойтись, однако использование её превращается в головную боль. Сейчас знакомлюсь с технологией Windows Forms, откровенно разочарован. Очередной Бейсик.
P.S. Для разработки настольных приложений есть более лучший вариант чем Windows Forms, это WPF.
Читайте также: