Как сделать dll файл

от admin

Статья Как создать dll библиотеку?

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

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

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

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

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

Но, тут вам звонит ваш коллега по работе и говорит: Ты знаешь, я тут вспомнил, когда я разрабатывал данный метод, я подумал, что возможно мне придется его использовать ещё где-то, и по этому я решил вынести его в отдельную сборку, в виде файла динамической библиотеки (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

Данная ошибка, говорит лишь о том, что был создан файл динамической библиотеки (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, появиться вот такое окно.

28422

В окне 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)

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

Программирование на C, C# и Java

Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode

Как создать dll в Visual Studio

DLL (Dynamic Link Library) — динамически подключаемая библиотека функций. Для библиотек DLL предполагается многократное использование различными программами. Поговорим о том, как создать библиотеку DLL в Visual Studio, используя языки программирования C и C#.

Создание dll на языке Си

Создаем в Visual Studio новый проект — консольное приложение.

Создаем в Visual Studio новый проект - vscode.ru

В запустившемся «Мастере приложений Win32» жмем кнопку «Далее». В следующем окне выбираем тип приложения: «Библиотека DLL»; также ставим галочку напротив параметра «Пустой проект». Жмем кнопку «Готово».

DynLib: библиотека для создания и работы с DLL

imageБиблиотека DynLib предоставляет удобные средства для разработчиков, использующих межмодульное взаимодействие (EXE<->DLL, DLL<->DLL) в своих проектах, и значительно сокращает время и количество кода.
DynLib стала неотъемлемым инструментом разработки. Под катом делимся результатами.

Недостатки традиционного подхода к реализации DLL
  1. отсутствие возможности использовать пространства имен
  2. большое количество служебного кода, необходимого:
    • при реализации динамической загрузки библиотек;
    • при реализации межмодульного взаимодействия через классы, за счет использования декскрипторов (или иных неявных структур) и классов-оберток;
    • при реализации механизмов возвращения ошибки, в случае, когда экспортируемые функции могут генерировать исключения.
Примеры использования DynLib
1. Использование обычной DLL

Задача. Динамически подключить и использовать библиотеку test_lib.dll, реализующую простые математические операции, с интерфейсом, представленным в заголовочном файле:
Решение. Необходимо написать следующий заголовочный файл и подключить его к проекту.
Препроцессор сгенерирует класс test::lib, выполняющий динамическую загрузку DLL и содержащий перечисленные функции sum, mul и epsilon. Для подключения DLL к приложению необходимо включить представленный заголовочный файл test_lib.hpp в исходный код. Далее следует создать объект класса test::lib. Доступ к экспортируемых функциям DLL возможен через ‘.’ или ‘->’.

2. Создание библиотеки calculator.dll

Задача. Написать библиотеку calculator.dll, которая должна вычислять сумму, произведение двух чисел и значение квадратного корня. Динамически загрузить библиотеку и вызвать каждую функцию.
Решение

4. Реализация библиотеки shapes.dll. Использование интерфейсов.

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

Как подключить библиотеку

Библиотека поставляется в виде заголовочных файлов. Никаких .lib и .dll не требуется. Для подключения требуется добавить следующую директиву:

Элементы библиотеки

Многие классы и макросы библиотеки DynLib могут использоваться самостоятельно и отдельно друг от друга.

DL_BLOCK

Служит контейнером для всех остальных макросов.

DL_NS_BLOCK

Служит контейнером для всех остальных макросов. Создает пространства имен для класса.
Макросы, которые описаны ниже кроме DL_EXPORT, должны быть помещены в DL_BLOCK или DL_NS_BLOCK

DL_C_LIBRARY

Назначение макроса — предоставить пользователю готовый класс, реализующий динамическую загрузку DLL и автоматический импорт функций. Макрос представлен как:

  • lib_class — имя класса, реализацию которого генерирует библиотека DynLib;
  • functions — перечисление функций, экспортируемых DLL. задается через список следующего формата
    (ret_type, call, (name, import_name), arguments)
    • ret_type — тип возвращаемого функцией значения;
    • call — формат вызова, например: __sdtcall, __cdecl и т.п.;
    • name — имя функции (для пользователя);
    • import_name — имя функции, заданной в таблице экспорта DLL, включая декорацию (если она есть). Если name и import_name совпадают, то import_name можно не указывать.
    • arguments — список (тип аргумента, имя аргумента, = значение по умолчанию), задающий входные аргументы. Имя аргумента и значение по умолчанию можно не указывать.;
    DL_RECORD

    Макрос DL_RECORD генерирует упакованную структуру данных для использования в межмодульном взаимодействии. Дополнительно создается конструктор со всеми перечисленными в макросе аргументами.

    DL_LIBRARY
    1. выступает в роли описания (документирования) интерфейса между EXE(DLL) и DLL;
    2. содержит необходимые структуры для автоматического экспорта функций библиотеки для разработчика;
    3. реализует класс, обеспечивающий загрузку DLL с заданным интерфейсом и предоставляющий доступ к экспортируемым функциям со стороны пользователя;
    4. обеспечивает корректное использование C++ исключений:
    DL_EXPORT
    • lib_class — полное имя класса, описывающего интерфейс взаимодействия (то имя класса, что использовалось в DL_LIBRARY);
    • lib_impl_class — полное имя класса класса, РЕАЛИЗУЮЩЕГО функции, указанные в интерфейсе взаимодействия.
    1. Создать класс (структуру);
    2. Определить каждую функцию из интерфейса как статическую. Функции должны находиться в области видимости public:;
    3. Произвести экспорт функций, написав конструкцию DL_EXPORT(lib, impl).
    DL_INTERFACE

    Макрос позволяет описать интерфейс класса и предоставить пользователю класс-обертку для работы с ним. Реализация класса-обертки обеспечивает корректное использование C++ исключений: Класс-обертка, генерируемая данным макросом, имеет разделяемое владение объектом, реализующего данный интерфейс. Разделяемое владение обеспечивается механизмом подсчета ссылок, т.е. когда происходит копирование объектов класса-обертки, вызывается внутренняя функция для увеличения счетчика ссылок, при уничтожении — внутренняя функция по уменьшению счетчика ссылок. При достижении счетчиком значения 0 происходит автоматическое удаление объекта. Доступ к методам интерфейса осуществляется через ‘.’ или ‘->’.
    Библиотека DynLib гарантирует безопасное использование классов-интерфейсов на границе EXE(DLL)<->DLL

    • interface_class — имя класса, реализацию которого генерирует библиотека DynLib;
    • methods — перечисление функций, описывающих интерфейс класса,
    dl::shared
    1. динамическое создание объекта класса T с аргументами, переданными в конструкторе;
    2. добавление счетчика ссылок и обеспечение разделяемого владения (подобно boost(std)::shared_ptr);
    3. неявное приведение к объекту класса, генерируемого макросом DL_INTERFACE.

    Примеры использования dl::shared представлены ниже:

    dl::ref

    Функция библиотеки, позволяющая привести любой объект к объекту класса-интерфейса, объявленному через DL_INTERFACE, с идентичным набором методов. Обычно такое поведение необходимо, когда имеется функция, принимающая в качестве аргумента класс-интерфейс, а ему следует передать объект, размещенный в стеке.
    Использовать функцию dl::ref нужно с осторожностью, поскольку объекты классов-интерфейсов, в этом случае не будут владеть переданными объектами, а управление временем жизни объекта и его использованием через классы-интерфейсы ложится на пользователя. Копирование объектов классов-интерфейсов, ссылающих на объекты, переданные через dl::ref, разрешено и вполне корректно (поскольку счетчика ссылок нет, то и изменять нечего — объекты классы-интерфейсов знают как здесь корректно работать).

    Создание библиотеки классов (.dll): неявное связывание

    Область применения: язык программирования C++, операционная система «Windows 7», среда разработки «Visual Studio Community 2017».

    Близкая по теме англоязычная статья на сайте «Microsoft Docs»: «Walkthrough: Create and use your own Dynamic Link Library (C++)» (по-русски «Пошаговое руководство: создание и использование DLL (C++)»).

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

    Создание проекта прикладной программы
    1. Создадим пустой проект с названием MyApp . Итак, пункт меню «Файл – Создать – Проект. ». В открывшемся окне «Создание проекта» в меню слева выберем пункт «Установленные – Visual C++». В меню в центре выберем пункт «Пустой проект». В этом же окне внизу в реквизите «Имя» вместо названия проекта по умолчанию указываем MyApp . (Реквизит «Расположение» оставим по умолчанию, галки «Создать каталог для решения» и «Добавить в систему управления версиями» я снял.) Запускаем создание проекта кнопкой «OK» в правом нижнем углу окна.

    2. Наша прикладная программа — это та же программа, которую я использовал для тестирования статической библиотеки классов в предыдущих постах. То есть добавляем в проект файл test_app.cpp. Для этого копируем этот файл в папку проекта MyApp (эта папка, напомню, находится по пути Расположение\Имя\ , составленном из упомянутых в первом пункте реквизитов «Расположение» и «Имя»). После этого я добавляю этот файл в проект через «Обозреватель решений» в ветку «Исходные файлы» нашего проекта.

    Включение файлов динамической библиотеки в прикладную программу
    3. Напомню, что в файл прикладной программы test_app.cpp включен интерфейс библиотеки классов в виде заголовочного файла mylib.h:
    Поэтому копируем заголовочный файл mylib.h из проекта нашей динамической библиотеки ProjectDLL в проект нашей прикладной программы. То есть копирую этот файл в папку проекта нашей прикладной программы и включаю в проект через «Обозреватель решений» в ветку «Файлы заголовков».

    4. Уберем из заголовочного файла mylib.h нашего проекта прикладной программы MyApp модификаторы __declspec(dllexport) , ведь в прикладной программе они не нужны, тут требуется не экспорт, а импорт классов.

    5. Как наша прикладная программа узнает, какие программные сущности нужно импортировать и откуда их импортировать? В данном посте речь идет про неявное связывание DLL и прикладной программы. Этот метод связывания подразумевает передачу компоновщику, входящему в состав компилятора, нужной для связывания информации (само связывание будет выполнено компоновщиком операционной системы на этапе загрузки прикладной программы (load time) в оперативную память). Такая передача происходит через файл библиотеки импорта .lib . Этот файл был создан компилятором при сборке проекта нашей DLL и находится в той же папке проекта DLL, что и файл самой DLL. (Я не упомянул о нем в посте о создании проекта DLL, потому что в тот момент в этом не было нужды.)

    Тут нужно отметить, что, несмотря на совпадение расширений ( .lib ) у статической библиотеки классов, про которую шла речь в предыдущих постах этой серии, и у библиотеки импорта, это совершенно разные файлы с совершенно разным содержимым. Это можно понять даже по разнице их размеров. Например, размер статической библиотеки, созданной в одном из предыдущих постов, составил 984 Кб, а размер библиотеки импорта, созданной в проекте по созданию нашей DLL, составил 8 Кб.

    Итак, копируем файл библиотеки импорта ProjectDLL.lib из папки Расположение\ProjectDLL\Release\ проекта по созданию DLL в папку Расположение\MyApp\ проекта нашей прикладной программы. Далее подключаем эту библиотеку импорта через свойства проекта. Для этого сначала на панели инструментов среды делаем активной конфигурацию решения Release и платформу решения x86. Теперь откроем окно свойств проекта. Я это делаю через «Обозреватель решений», щелкнув правой кнопкой мыши по названию нашего проекта. В открывшемся контекстном меню следует выбрать самый последний пункт «Свойства». В открывшемся окне «Страницы свойств MyApp» сначала следует сверху в реквизитах «Конфигурация» и «Платформа» проверить, что выбраны нужные нам конфигурация решения «Release» и платформа решения «x86» (она же — «Win32») (свойства проекта можно устанавливать разными для разных конфигураций и платформ решения).

    После этого в меню слева выберем пункт «Свойства конфигурации – Компоновщик – Ввод». Далее в списке свойств справа в значение свойства «Дополнительные зависимости» следует добавить имя нашей библиотеки импорта ProjectDLL.lib . Сохраним значения свойств проекта с помощью кнопки «OK» в правом нижнем углу окна.

    Готово
    Теперь уже можно запустить компиляцию (сборку) проекта MyApp нашей прикладной программы с помощью пункта меню «Сборка – Собрать решение». В результате сборки будет создана папка Расположение\MyApp\Release\ , в которой появится исполняемый файл нашей прикладной программы MyApp.exe .

    Однако, если запустить этот файл на выполнение, получим следующее сообщение операционной системы об ошибке: «Запуск программы невозможен, так как на компьютере отсутствует ProjectDLL.dll. Попробуйте переустановить программу.».

    Это логично. Вспомним порядок неявного связывания. При загрузке (load time) исполняемого файла в оперативную память компоновщик операционной системы пытается выполнить связывание нашей прикладной программы с динамической библиотекой ProjectDLL.dll . Для этого этот компоновщик запускает поиск файла динамической библиотеки ProjectDLL.dll . Порядок этого поиска может варьироваться в зависимости от разнообразных факторов. Об этом можно почитать в большой англоязычной статье «Dynamic-Link Library Search Order» на сайте «Microsoft Docs» (я недавно делал ее перевод на русский).

    Сейчас наша DLL находится в папке проекта по ее созданию Расположение\ProjectDLL\Release\ и эта папка не входит в поисковый список каталогов (папок), в которых операционная система разыскивает нашу DLL. Поэтому операционная система не может найти нашу DLL и выдает вышеуказанное сообщение об ошибке.

    Зато, к примеру, каталог, из которого запускается исполняемый файл нашей прикладной программы, входит в вышеупомянутый поисковый список каталогов (папок). Поэтому я копирую нашу DLL ProjectDLL.dll из каталога Расположение\ProjectDLL\Release\ в каталог Расположение\MyApp\Release\ и снова запускаю исполняемый файл нашей прикладной программы MyApp.exe .

    Теперь наша прикладная программа отрабатывает без ошибок:

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

    Но тут нужно помнить, что для 32-разрядных прикладных программ системный каталог в 32-разрядной версии операционной системы «Windows» — это каталог ..\Windows\System32\ , а для 64-разрядной версии операционной системы «Windows» — это каталог ..\Windows\SysWOW64\ . У меня как раз второй случай, 64-разрядная версия операционной системы «Windows 7» (папка ..\Windows\System32\ тоже присутствует, но помещенную туда 32-разрядную версию нашей DLL операционная система не находит).

    Оптимизация интерфейса DLL
    Теперь перейдем к обещанным в начале поста изменениям в заголовочный файл (интерфейс DLL) mylib.h.

    Как мы увидели, помечать импортируемые в нашу прикладную программу классы в качестве «импортируемых» необязательно. При сборке прикладной программы компоновщик, ориентируясь на информацию из библиотеки импорта, прекрасно понимает, какие классы являются импортируемыми. Однако, помечать импортируемые классы в качестве «импортируемых» в исходном коде всё-таки рекомендуют. Это упростит и убыстрит работу компоновщика. Такая пометка классов выполняется с помощью модификатора __declspec(dllimport) точно так же, как при экспорте классов при создании DLL применяется модификатор __declspec(dllexport) .

    Получается, что при сборке DLL в заголовочном файле mylib.h в экспортируемых классах должны стоять модификаторы экспорта, а при сборке прикладной программы в том же заголовочном файле в тех же классах (только теперь импортируемых) должны стоять модификаторы импорта. То есть разработчик DLL должен иметь две версии этого заголовочного файла — одну для сборки DLL, а другую — для передачи (продажи) разработчику прикладной программы. Естественно, что это неудобно.

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

    Теперь, если в проекте существует символ-макрос ProjectDLL_EXPORTING , то классы будут помечены модификатором экспорта. Если же символ-макрос ProjectDLL_EXPORTING не определен, то классы будут помечены модификатором импорта. В проекте по созданию DLL разработчик DLL определяет указанный символ-макрос, а в проекте по созданию прикладной программы разработчик прикладной программы этот символ-макрос не определяет. Таким образом разработчик DLL имеет только одну версию заголовочного файла mylib.h — и для разработки DLL, и для передачи (продажи) разработчику прикладной программы.

    При использовании в среде «Visual Studio Community 2017» специализированного шаблона для создания проекта по созданию DLL среда сама вставляет вышеописанную конструкцию в заголовочный файл и сама определяет символ-макрос с именем ИмяПроекта_EXPORTING . При использовании для создания DLL пустого проекта (как это делал я в этой серии постов) разработчик DLL может сам вставить вышеуказанную конструкцию в заголовочный файл и сам определить соответствующий символ-макрос.

    Я определил символ-макрос ProjectDLL_EXPORTING в свойствах проекта. Открываем свойства проекта DLL для соответствующей конфигурации (конфигурация решения «Release», платформа решения «x86»). Выбираем в левом меню пункт «Свойства конфигурации – С/С++ – Препроцессор». Далее, справа, в списке свойств выбираем свойство «Определения препроцессора» и добавляем в значение этого свойства символ-макрос ProjectDLL_EXPORTING . Сохраняем свойства проекта с помощью кнопки «OK» в правом нижнем углу окна свойств.

    Читать:
    Какое число надо умножить

Похожие статьи