Russian Qt Forum
Ноябрь 24, 2024, 06:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: Загрузка классов из динамических библиотек???  (Прочитано 37687 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« : Январь 14, 2009, 09:17 »

Доброго времени суток!

Подскажите пожалуйста, каким образом можно загрузить класс из динамической библиотеки, используя механизмы QT4?

Я почитал документацию, и нашел только 2 класса QPluginLoader и QLibrary.
Но как я понял с помощью них можно релизовать только вызов функций (по примерам из QT).

ЗЫ: мне нужно в библиотеку засунуть QT-шный класс (например QThread и т.д)
Записан

ArchLinux x86_64 / Win10 64 bit
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Январь 14, 2009, 09:36 »

почитай тут
Записан

Юра.
Rcus
Гость
« Ответ #2 : Январь 14, 2009, 09:41 »

Руководство по созданию плагинов:
http://doc.trolltech.com/4.4/plugins-howto.html
Пример:
http://doc.trolltech.com/4.4/tools-plugandpaint.html
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Январь 14, 2009, 10:21 »

Я это читал, даже пробовал .. это все работает, но мне нужно нечто другое (я так думаю)

Суть: мне к моей проге нужно сделать "подключаемый модуль" (скорее всего плагин Улыбающийся ) который работает сам по себе и реализует некий потокол (к примеру конкретно Modbus) ...

т.е если бы я делал этот модуль не плагином - то он бы представлял из себя экземпляр класса типа QThread, который я бы запускал из основной программы, а сам этот класс работал бы сам по себе вечно там в цикле и чо-то делал по некому алгоритму! Улыбающийся

но как такое же самое проделать, но сделав мой класс - плагином я пока затрудняюсь придумать !
т.е. мне нужно из библиотеки "выдернуть" класс (который является наследником QThread к примеру)...

в примерах Assistent , Examples и т.п. "выдергиваются" функции!!!

и попутно вопрос, в чем разница по сути использования QPluginLoader и QLibrary??? если и там и там при загрузке мы в конечном итоге выдергиваем из *.dll / *.so нужные нам ф-ции???
« Последнее редактирование: Январь 14, 2009, 10:24 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kirill
Гость
« Ответ #4 : Январь 14, 2009, 10:30 »

В либе должна быть функция которая возвратит указатель на этот класс.

Дальше обращаешся к нему из основной программы, приведя void к нужному типу.
Например:

Код
C++ (Qt)
typedef void * CreateFormT(const char *, const char *, void **, void *, void *);
CreateFormT *TFCreateForm;    //функция загрузки формы
 
QLibrary formLib("form.dll");
TFCreateForm = (CreateFormT *) formLib.resolve("_CreateForm");
void *wid = TFCreateForm("Form.xml", ".data.xml", &m_form, NULL, NULL);
 
QWidget *widget_ = (QWidget *)wid; //вот здесь я получил QWidget

Записан
ритт
Гость
« Ответ #5 : Январь 14, 2009, 10:55 »

автору нужно наследника кутред -> плагин будет линковаться с кутэкоре -> можно обойтись без приведения воидстар к нужному типу.

минималистичный вариант может ограничиться строкой:
Код:
QThread* createObject(QObject* parent) const { return new MyThread(parent); }
но это ещё не будет плагином - плагин должен содержать некий интерфейс, известный приложению -> читать ассистант по QPlugin, QPluginLoader, plug & paint example, etc.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Январь 14, 2009, 11:52 »

to kirill, константин

спс за наводку! Улыбающийся

Цитировать
В либе должна быть функция которая возвратит указатель на этот класс.

т.е как тут где - то на форумах написано - нужно в либе сделать функцию, при вызове которой - она возвращала класс??

типа этого:
Код:
//либа .h
class MyClass : public QThread
{
    Q_OBJECT

public:
    MyClass ();

private :
    void setOpenFileName();
};

//это ф-ция которая создает новый класс
MyClass  MyFunc = new MyClass ; //и эту функцию нужно экспортировать из библиотеки????


или как?

и:
Цитировать
автору нужно наследника кутред -> плагин будет линковаться с кутэкоре -> можно обойтись без приведения воидстар к нужному типу.

минималистичный вариант может ограничиться строкой:
Код:

QThread* createObject(QObject* parent) const { return new MyThread(parent); }

но это ещё не будет плагином - плагин должен содержать некий интерфейс, известный приложению -> читать ассистант по QPlugin, QPluginLoader, plug & paint example, etc.

1. так в чем существенная разница м/у библой плагина и просто библой с функциями?
2. и как лучше мне поступить в моем случае: создать "модуль" как плагин или просто как обычную библу?


« Последнее редактирование: Январь 14, 2009, 11:56 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kirill
Гость
« Ответ #7 : Январь 14, 2009, 12:29 »

нужно в либе сделать функцию, при вызове которой - она возвращала класс

У тебя дб функция которая создаст класс и вернет указатель на него.
То что ты написал не совсем верно.

Надо примерно так:
Вызывать из основной программы будешь функцию

Код:
IMPORT_EXPORT void * _CreateThread(/* параметры*/);
А в ней создаешь экземпляр класса MyClass и вернешь указатель на него.

Код
C++ (Qt)
void * _CreateThread(/* параметры*/)
{
  MyClass * cl = new MyClass();
  return cl;
}
Получив этот указатель в основной программе конвертишь его из void * в MyClass *.

Я так делал для QWidget, насколько это верно для QThread не знаю, слушай Константина.
Записан
ритт
Гость
« Ответ #8 : Январь 14, 2009, 13:49 »

ррр...господа, читайте внимательнее.

Код:
//либа .h
class MyClass : public QThread
{
    Q_OBJECT

public:
    MyClass ();

private :
    void setOpenFileName();
};

MyClass  MyFunc = new MyClass; // неправильно

//это ф-ция которая создает новый класс
QThread* createObject(QObject* parent) const // правильно
{ return new MyClass(parent); }

так получаем либу, из которой будем дёргать createObject для получения QThread*. если приложение линкуется с этой либой, советую в хедере оставить лишь
Код:
class QObject;
class QThread;

QThread* createObject(QObject* parent) const;
, а остальное убрать в .cpp - тогда, подключая хедер динамической библиотеки, избавляемся от сборки ненужного кода.

фактически плагин отличается от либы лишь специальными функциями для {,де}инициализации, проверки версий и т.д.
QPlugin скрывает эти функции от пользователя - остаётся лишь обозначить интерфейс и сам плагин через определённые макросы.
в итоге видимая разница между плагином и либой - для подключения либы нужен её хедер; для подгрузки плагина нужен только хедер интерфейса (обычно чисто-абстрактный), т.к. интерфейс определяется на стороне сервера, а не на сторонее клиента (либы).

ещё вопросы?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Январь 14, 2009, 13:52 »

В общем решил сделать свой подключаемый модуль плагином....

вот код interfaces.h
Код:
#ifndef INTERFACES_H
#define INTERFACES_H

class MyModuleInterface
{
public:
    virtual ~MyModuleInterface() {}
    virtual void* MyModuleCreate() ;//const = 0;
};

Q_DECLARE_INTERFACE(MyModuleInterface, "mywww.My.MyModuleInterface/1.0")

#endif

вот код myPlug.h
Код:
#ifndef MYPLUG_H
#define MYPLUG_H

#include <QObject>
#include <QThread>

#include "../app/interfaces.h"

//это собственно определение моего модуля, который должен чо-то выполнять
class MyModule : public QThread
{
    Q_OBJECT

protected:
    void run();
/*
тут добавлю потом в public, private различные необхлдимые мне методы
*/
};

//это как я понял плагин с интерфейсом
class MyModulePlugin : public QObject,
                       public MyModuleInterface
{
    Q_OBJECT
    Q_INTERFACES(MyModuleInterface)

public:
    void* MyModuleCreate();
};

#endif


вот код myPlug.cpp
Код:
#include <QtGui>
#include "myPlug.h"


//
void MyModule::run()
{
    printf("Module is Running \n");
    /*
    тут будет собственно реализован к примеру алгоритм работы модуля
    */
}

//
void* MyModulePlugin::MyModuleCreate()
{
    return new MyModule();
}

Q_EXPORT_PLUGIN2(mymoduleplugin, MyModulePlugin)


компилирую пока под Windows XP при помощи MinGW

и компилятор выдает следующее:
Цитировать
Creating library file: release\libplug.a
release\moc_myPlug.o(.text$_ZN14MyModulePluginD1Ev[MyModulePlugin::~MyModulePlug
in()]+0x12):moc_myPlug.cpp: undefined reference to `vtable for MyModuleInterface
'
release\moc_myPlug.o(.text$_ZN14MyModulePluginD0Ev[MyModulePlugin::~MyModulePlug
in()]+0x13):moc_myPlug.cpp: undefined reference to `vtable for MyModuleInterface
'
collect2: ld returned 1 exit status
mingw32-make[1]: *** [release\plug.dll] Error 1
mingw32-make[1]: Leaving directory `D:/projects/plg2/lib'
mingw32-make: *** [release] Error 2


« Последнее редактирование: Январь 14, 2009, 14:32 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
ритт
Гость
« Ответ #10 : Январь 14, 2009, 14:36 »

/* чуть не нагрубил */

на кой хрен в interfaces.h MyModuleInterface имеет чисто-виртуальный типизированный конструктор? бред!

зачем в myPlug.h задекларирован MyModule, если вне плагина он использоваться не будет (будет использоваться суперкласс - QThread)?
Записан
Dendy
Гость
« Ответ #11 : Январь 14, 2009, 15:10 »

/* чуть не нагрубил */

Закройте глаза, расслабьтесь, глубокий вход...

на кой хрен в interfaces.h MyModuleInterface имеет чисто-виртуальный типизированный конструктор? бред!

Ваше сознание проясняется, вы уже видите знак тильды, говорящий что это деструктор. Виртуальный деструктор это хорошо, это правильно, вы чувствуете блаженство.

зачем в myPlug.h задекларирован MyModule, если вне плагина он использоваться не будет (будет использоваться суперкласс - QThread)?

Вы чувствуете как поток тёплой энергии расходится по вашему телу.

2 kuzulis : Наверное вы забыли написать тело MyModuleInterface::MyModuleCreate();

2 Константин: Выдыхаем.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #12 : Январь 14, 2009, 15:10 »

в общем плагин собирается если вместо:

Код:
virtual void* MyModuleCreate() ;//const = 0;

написать:

Код:
virtual void* MyModuleCreate() = 0;

Цитировать
на кой хрен в interfaces.h MyModuleInterface имеет чисто-виртуальный типизированный конструктор? бред!
деструктор! так написано в доке! что в хейдере интерфейсов должны быть чисто виртуальные ф-ции! и необходимо объявлять только деструктор!  Строит глазки



Цитировать
зачем в myPlug.h задекларирован MyModule, если вне плагина он использоваться не будет (будет использоваться суперкласс - QThread)?
ну так MyModule - есть потомок QThread, и в него мне надо будет добавить дополнительные методы... вот я сразу с "методами что в комментариях" типо и задекларировал его... Улыбающийся



  





« Последнее редактирование: Январь 14, 2009, 15:12 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Январь 14, 2009, 15:21 »

Цитировать
ну так MyModule - есть потомок QThread, и в него мне надо будет добавить дополнительные методы... вот я сразу с "методами что в комментариях" типо и задекларировал его... Улыбающийся

хотя думаю это неправильно, и вообще я так понял тут изза того что имеется такая "фича" как интерфейс - то :
Цитировать
virtual void* MyModuleCreate() ;
   
декларировать наверное ненужно, т.к. можно сделать, чтобы MyModule создавался в конструкторе интерфейса, что-ли....

а уже декларировать в интерфейсе MyModuleInterface нужно такие методы как к примеру:

Start() - запуск модуля
Stop() - останов модуля
State() - статус модуля и т.п,

которые я реализую в классе MyModule   ...

Я правильно мыслю? Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
ритт
Гость
« Ответ #14 : Январь 14, 2009, 15:26 »

кузулис, похоже, подправил код, пока я отвечал...
изначально там было
Код:
class MyModuleInterface
{
public:
    virtual ~MyModuleInterface() {}
    virtual void* MyModuleInterface();
//...
, что подтверждала ошибка компилятора (которая сейчас тоже раза в два короче)

2Dendy, "глубокий вход" - это сильно Улыбающийся
Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.194 секунд. Запросов: 22.