Russian Qt Forum

Qt => Общие вопросы => Тема начата: lolbla2 от Февраль 22, 2012, 17:06



Название: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 22, 2012, 17:06
Хочу сделать свой класс в длл и чтобы длл можно было подключать динамически, то есть не прописывать файле проекта её, а подключать при помощи например QLibrary::load() или же аналог Winapi LoadLibrary. Возможно ли так сделать? а то у меня так получается только с функциями, а с классами никак, экспорт классов как реализовать? Может мне надо использовать плагины? Но в плагинах же вроде можно только отнаследовать стандартные Qt классы? А если мне надо с нуля свой класс сделать и чтобы потому в программе подключить эту длл и создавать объекты этого класса таким образом  
Код:
Myclass obj;
 

P.S. Давно эта проблема интересует, но раньше как-то забил на это не получилось и фиг с ним, а ща снова заинтересовался как так сделать...


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: kuzulis от Февраль 22, 2012, 18:00
Блжад, а поискать по форуму не судьба?  >:(


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 22, 2012, 18:48
Блжад, а поискать по форуму не судьба?  >:(

 подходящего не нашёл. Если знаешь по теме ответь.


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Ground от Февраль 23, 2012, 04:37
Тут нужно смотреть, знает ли приложение, к которому ты подключаешь DLL Qt или нет. Если не знает, то нужно делать интерфейс для класса, из которого убирать все упоминания о Qt, вот примерно так:
Код
C++ (Qt)
#ifdef ICLIENT_EXPORTS
#define ICLIENT_API __declspec(dllexport)
#else
#define ICLIENT_API __declspec(dllimport)
#endif
 
class ICLIENT_API IClient {
public:
   // Конструктор
   IClient();
   // Деструктор
   ~IClient();
 
   // Метод, выполняющий попытку подключения к серверу
   int connectToServer();
   // Принудительное отключение клиента
   int disconnectFromServer();
 
   // Установка сетевых настроек для клиента
   int setParameters(char* serverAddress, int port);
 
   // Состояние клиента
   int isConnected();
 
   // Отправка сообщения серверу о готовности клиента к получению данных
   int sendClientIsReady();
   // Отправка пакета с информацией об имени отображаемого в память файла
   int sendMMFPackage(char* MMFName);
   // Отправка данных об элементе для регистрации на сервере
   int sendRegInfoPackage(int elementID, int count,
                          int* startBytes, int* bytesCount);
   // Отправка запроса на получение описания к элементу
   int sendDBRequestPackage(int elementID, int startByte,
                            int startBit, int bitsCount);
   // Установка буфера для сброса полученной информации
   int setBuffer(char* buffer);
 
   // Обработка событий сети
   int start();
 
private:
   Client* mClient;
   char* mBuffer;
};
 
Везде инты, чары - благодать. А Qt будет работать в классе Client, он тут объявлен как указатель, в конструкторе класса создается. CPP-файл заполняется как обычно, никаких особенностей там нет.
Только есть один момент, если у тебя в DLL есть что-то, отправляющее сигналы (сеть, например), то работать это не будет, пока ты в программе, к которой подключаешь DLL не создашь QCoreApplication или QApplication.

Потом компилишь свою либу, получаешься на выходе, для винды: lib + dll. Либ явно подключаешь к проекту LIBS += твоя_либа. В сам код делаешь #include "твоя_либа.h", все, можешь в коде делать экземпляр своего класса из либы и работать.


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 09:35
Тут нужно смотреть, знает ли приложение, к которому ты подключаешь DLL Qt или нет. Если не знает, то нужно делать интерфейс для класса, из которого убирать все упоминания о Qt, вот примерно так:
Код
C++ (Qt)
#ifdef ICLIENT_EXPORTS
#define ICLIENT_API __declspec(dllexport)
#else
#define ICLIENT_API __declspec(dllimport)
#endif
 
class ICLIENT_API IClient {
public:
   // Конструктор
   IClient();
   // Деструктор
   ~IClient();
 
   // Метод, выполняющий попытку подключения к серверу
   int connectToServer();
   // Принудительное отключение клиента
   int disconnectFromServer();
 
   // Установка сетевых настроек для клиента
   int setParameters(char* serverAddress, int port);
 
   // Состояние клиента
   int isConnected();
 
   // Отправка сообщения серверу о готовности клиента к получению данных
   int sendClientIsReady();
   // Отправка пакета с информацией об имени отображаемого в память файла
   int sendMMFPackage(char* MMFName);
   // Отправка данных об элементе для регистрации на сервере
   int sendRegInfoPackage(int elementID, int count,
                          int* startBytes, int* bytesCount);
   // Отправка запроса на получение описания к элементу
   int sendDBRequestPackage(int elementID, int startByte,
                            int startBit, int bitsCount);
   // Установка буфера для сброса полученной информации
   int setBuffer(char* buffer);
 
   // Обработка событий сети
   int start();
 
private:
   Client* mClient;
   char* mBuffer;
};
 
Везде инты, чары - благодать. А Qt будет работать в классе Client, он тут объявлен как указатель, в конструкторе класса создается. CPP-файл заполняется как обычно, никаких особенностей там нет.
Только есть один момент, если у тебя в DLL есть что-то, отправляющее сигналы (сеть, например), то работать это не будет, пока ты в программе, к которой подключаешь DLL не создашь QCoreApplication или QApplication.

Потом компилишь свою либу, получаешься на выходе, для винды: lib + dll. Либ явно подключаешь к проекту LIBS += твоя_либа. В сам код делаешь #include "твоя_либа.h", все, можешь в коде делать экземпляр своего класса из либы и работать.

Вы меня немного не поняли.... lib это статическая версия библиотеки, а я говорю о динамике, чтобы никаких LIBS +=... в проекте делать не надо было, у меня к примеру есть толькo .dll.

Например есть Mydll.dll. Там есть некоторый класс Myclass;

подключаю её следующим образом:
Код:
QLibrary lib;
lib.load("Mydll.dll);

И далее хочу создать экземпляр класса:

Код:
Myclass obj;

Так вот при динамике так не получается, если .lib подрубить да ещё и .h файл длл это уже статическое подключение, а я говорю о ДИНАМИКЕ. Про то что ты мне сказал это я и так знаю что так будет работать.

P.S. Вроде надо ещё дописывать extern "C" перед __declspec(dllexport),а то иначе чото он вроде не пашет по крайне мере в MSVS


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Ground от Февраль 23, 2012, 10:34
Вы меня немного не поняли.... lib это статическая версия библиотеки, а я говорю о динамике, чтобы никаких LIBS +=... в проекте делать не надо было, у меня к примеру есть толькo .dll.

Например есть Mydll.dll. Там есть некоторый класс Myclass;

подключаю её следующим образом:
Код:
QLibrary lib;
lib.load("Mydll.dll);

И далее хочу создать экземпляр класса:

Код:
Myclass obj;

Так вот при динамике так не получается, если .lib подрубить да ещё и .h файл длл это уже статическое подключение, а я говорю о ДИНАМИКЕ. Про то что ты мне сказал это я и так знаю что так будет работать.

P.S. Вроде надо ещё дописывать extern "C" перед __declspec(dllexport),а то иначе чото он вроде не пашет по крайне мере в MSVS

Lib тоже разный бывает. В одном случае там действительно объектный код функций (и тогда это статическая линковка), а иногда там просто указания для линкера, как ресолвить функции в dll.
Единственное, я копал про это для MSVC2010, не знаю как GCC себя ведет. UPD: Вспомнил, не далее как вчера пробовал в GCC такую же схему, подключил .a к проекту на чистом C++, хедер от этого класса. И дальше спокойно создавал объекты. Таким образом, вам даже можно обойтись без QLibrary, насколько я понимаю.

P.S. Вроде надо ещё дописывать extern "C" перед __declspec(dllexport),а то иначе чото он вроде не пашет по крайне мере в MSVS
Есть такое. Вот эти строчки:
Код
C++ (Qt)
#ifdef ICLIENT_EXPORTS
#define ICLIENT_API __declspec(dllexport)
#else
#define ICLIENT_API __declspec(dllimport)
#endif
А потом в хедере класса:
Код
C++ (Qt)
class ICLIENT_API IClient
{
   ...
}


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 10:41
Вы меня немного не поняли.... lib это статическая версия библиотеки, а я говорю о динамике, чтобы никаких LIBS +=... в проекте делать не надо было, у меня к примеру есть толькo .dll.

Например есть Mydll.dll. Там есть некоторый класс Myclass;

подключаю её следующим образом:
Код:
QLibrary lib;
lib.load("Mydll.dll);

И далее хочу создать экземпляр класса:

Код:
Myclass obj;

Так вот при динамике так не получается, если .lib подрубить да ещё и .h файл длл это уже статическое подключение, а я говорю о ДИНАМИКЕ. Про то что ты мне сказал это я и так знаю что так будет работать.

P.S. Вроде надо ещё дописывать extern "C" перед __declspec(dllexport),а то иначе чото он вроде не пашет по крайне мере в MSVS

Lib тоже разный бывает. В одном случае там действительно объектный код функций (и тогда это статическая линковка), а иногда там просто указания для линкера, как ресолвить функции в dll.
Единственное, я копал про это для MSVC2010, не знаю как GCC себя ведет. UPD: Вспомнил, не далее как вчера пробовал в GCC такую же схему, подключил .a к проекту на чистом C++, хедер от этого класса. И дальше спокойно создавал объекты. Таким образом, вам даже можно обойтись без QLibrary, насколько я понимаю.

P.S. Вроде надо ещё дописывать extern "C" перед __declspec(dllexport),а то иначе чото он вроде не пашет по крайне мере в MSVS
Есть такое. Вот эти строчки:
Код
C++ (Qt)
#ifdef ICLIENT_EXPORTS
#define ICLIENT_API __declspec(dllexport)
#else
#define ICLIENT_API __declspec(dllimport)
#endif
А потом в хедере класса:
Код
C++ (Qt)
class ICLIENT_API IClient
{
   ...
}

Нет такого, надо тогда хотя бы так писать
Код
C++ (Qt)
#ifdef ICLIENT_EXPORTS
#define ICLIENT_API extern "C" __declspec(dllexport)
#else
#define ICLIENT_API extern "C" __declspec(dllimport)
#endif
А потом в хедере класса:
Код
C++ (Qt)
class ICLIENT_API IClient
{
   ...
}
Ну это мелочи

А по-моему вопрос так нового ничего и не узнал к сожалению((( Понимаешь охото без подключения всяких .h файлов длл и без .lib работать с классами в .dll. Такое наверно невозможно?


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Ground от Февраль 23, 2012, 10:47
Ну это мелочи
Для студии да, ты все верно написал. А мой вариант - это макрос для Qt.

А по-моему вопрос так нового ничего и не узнал к сожалению((( Понимаешь охото без подключения всяких .h файлов длл и без .lib работать с классами в .dll. Такое наверно невозможно?
Ну вот статья, там про все это расписано: http://www.rsdn.ru/article/baseserv/dlluse.xml


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Alex Custov от Февраль 23, 2012, 10:55
Понимаешь охото без подключения всяких .h файлов длл и без .lib работать с классами в .dll. Такое наверно невозможно?

То как ты хочешь - невозможно. Класс должен быть явным образом объявлен, чтобы использовать его в C++ коде именно так, как ты показал.

Теоретически, можно использовать Qt-шный metaobject и вызывать методы через него. Проблема в том, что класс должен быть заточен под это.


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 11:22
Понимаешь охото без подключения всяких .h файлов длл и без .lib работать с классами в .dll. Такое наверно невозможно?

То как ты хочешь - невозможно. Класс должен быть явным образом объявлен, чтобы использовать его в C++ коде именно так, как ты показал.

Теоретически, можно использовать Qt-шный metaobject и вызывать методы через него. Проблема в том, что класс должен быть заточен под это.

то есть таким образом как я указал можно вызывать только функции из длл да? Чтобы работать с классами я должен явно подключать длл? Всё верно ? ну я так и думал.


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Alex Custov от Февраль 23, 2012, 11:32
то есть таким образом как я указал можно вызывать только функции из длл да?

Грубо говоря - да. Не совсем понятно зачем это нужно, напиши пример использования.


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 12:56
то есть таким образом как я указал можно вызывать только функции из длл да?

Грубо говоря - да. Не совсем понятно зачем это нужно, напиши пример использования.

Например хочу свой класс сделать чтобы его использовали другие люди, но чтобы ничего не меняли. А если .h файл доступен, то они могут например private функции сделать public


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: mutineer от Февраль 23, 2012, 12:59
Например хочу свой класс сделать чтобы его использовали другие люди, но чтобы ничего не меняли. А если .h файл доступен, то они могут например private функции сделать public

Если они так сдлеают, то ССЗБ:) ну или можно по образу Qt оставить в .h только публичные методы


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 13:45
Например хочу свой класс сделать чтобы его использовали другие люди, но чтобы ничего не меняли. А если .h файл доступен, то они могут например private функции сделать public

Если они так сдлеают, то ССЗБ:) ну или можно по образу Qt оставить в .h только публичные методы
а остальные куда деть тогда? Прямо внутри публичных функций что ли реализовывать?

P.S.: а расшифровку ССЗБ можно?))


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: mutineer от Февраль 23, 2012, 13:48
Сам Себе Злобный Буратино. Короче, если меняешь хедеры либы при ее использовании - то винить в проблемах можешь только себя


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: Ground от Февраль 23, 2012, 13:56
а остальные куда деть тогда? Прямо внутри публичных функций что ли реализовывать?
Делай интерфейс для своего класса, где только публичные функции. Т.е. просто создаешь еще один класс, внутрь него заворачиваешь свой секретный класс и радуешься)


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: mutineer от Февраль 23, 2012, 13:58
а остальные куда деть тогда? Прямо внутри публичных функций что ли реализовывать?

Посмотри сорцы любого Qt-класса - увидишь как оно там


Название: Re: Подскажите как реализовать в дллсвой класс?
Отправлено: lolbla2 от Февраль 23, 2012, 14:11
а остальные куда деть тогда? Прямо внутри публичных функций что ли реализовывать?

Посмотри сорцы любого Qt-класса - увидишь как оно там

ну тогда получается потенциальный пользователь (программист) либы может наоборот сделать публичные методы приватными. это тоже не есть гуд)

Кстати в Builder C++ в .h файлах помню там и public, и private, и protected. Помню ещё там какой-то метод нужен был приватный я его в паблик засунул и радовался пользовался.


Название: Re: Подскажите как реализовать в дллсвой кла&
Отправлено: mutineer от Февраль 23, 2012, 14:15
а остальные куда деть тогда? Прямо внутри публичных функций что ли реализовывать?

Посмотри сорцы любого Qt-класса - увидишь как оно там

ну тогда получается потенциальный пользователь (программист) либы может наоборот сделать публичные методы приватными. это тоже не есть гуд)

Кстати в Builder C++ в .h файлах помню там и public, и private, и protected. Помню ещё там какой-то метод нужен был приватный я его в паблик засунул и радовался пользовался.

Если он так сделает - то это уже не твоя пробема

А если бы у тебя с этим методом возникли бы проблемы - в этом был бы виноват только то, а не девелоперы билдера:)