Как экспортировать класс С++ из DLL?
У меня есть класс, который имеет две перегруженные функции. Как экспортировать его из DLL, а также как использовать его другими классами С++? Мой класс выглядит следующим образом:
#define DECLDIREXP __declspec(dllexport)
#define DECLDIRIMP __declspec(dllimport)
class DECLDIREXP xyz
{
public:
void printing();
void printing(int a);
};
using namespace std;
void xyz::printing()
{
cout<<"hello i donot take any argument";
}
void xyz::printing(int a)
{
cout<<"hello i take "<< a <<"as argument";
}
Ответы
Ответ 1
Общим подходом является наличие одного макроса (пусть он вызывает его EXPORT
), который либо расширяется до dllimport
, либо dllexport
в зависимости от того, установлено ли какое-то определение "создание DLL прямо сейчас",
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
class EXPORT xyz {
// ...
};
Идея заключается в том, что при создании вашей DLL вы добавляете MAKEDLL
в определения препроцессора. Таким образом, весь код будет экспортироваться. Клиенты, которые ссылаются на вашу DLL (и, следовательно, включают этот заголовочный файл), вообще ничего не должны делать. Не определяя MAKEDLL
, они автоматически импортируют весь код.
Преимущество такого подхода заключается в том, что бремя получения макросов вправо перемещается от многих (клиентов) только к автору DLL.
Недостатком этого является то, что при использовании вышеприведенного кода уже невозможно просто скомпилировать код непосредственно в некоторый клиентский модуль, так как невозможно определить макрос EXPORT
до нуля. Для этого вам нужно будет иметь еще одну проверку, которая, если она истинна, ничего не определяет EXPORT.
В несколько другой теме: во многих случаях невозможно (или желательно!) экспортировать полный класс. Вместо этого вы можете просто экспортировать нужные символы. Например, в вашем случае вы можете просто экспортировать два общедоступных метода. Таким образом, все частные/защищенные члены не будут экспортироваться:
class xyz
{
public:
EXPORT void printing();
EXPORT void printing(int a);
};
Ответ 2
Как я помню, обычно вы экспортируете не класс, а функцию factory, которая создает новый экземпляр класса и возвращает указатель. Объявление класса находится в заголовочном файле для времени компиляции.
Возможно, я ошибаюсь в примере (это было давно), но вот как это должно выглядеть примерно так:
Заголовочный файл (.h):
class MyClass { ... };
extern "C" DLL_API MyClass* createMyClass();
Исходный файл (.cpp):
DLL_API MyClass* createMyClass() {
return new MyClass();
}
Определите MY_DLL_EXPORT во время компиляции, см. пример ответа.
Ответ 3
Один из вариантов:
Используйте по умолчанию определенный макрос локальный для проекта.
Макросы, определенные по умолчанию, локальны для проекта в нижерасположенном месте:
Свойства → C/С++ → Препроцессор → Определение препроцессора.
Пример:
Предположим, что ваше имя проекта: MyDLL
Макрос по умолчанию для этого проекта: MYDLL_EXPORTS
#ifdef MYDLL_EXPORTS
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT Class_Name {
//....
}
Ответ 4
При компиляции вашей библиотеки вы должны определить макрос (определение препроцессора командной строки), позвоните ему MY_DLL_EXPORT
.
Затем в вашем коде библиотеки сделайте что-то вроде этого:
#ifdef MY_DLL_EXPORT
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif
class DLL_API some_class { /*...*/ }