Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.14.246.148] |
|
Сообщ.
#1
,
|
|
|
Здравствуте!
Что делаю: мне надо написать динамически подгружаемую библиотеку(so или dll) в котором будет описан некий класс, затем, подгрузив библиотеку, создать экземпляр класса, хранящегося в библиотеке, и работать с ним. Могу сказать, что попытки с моей стороны были! Точнее библиотеку с классом я написал(вроде как, т.е. она компилится и создаётся без проблем), но вот как получить правилино создать экземпляр класса вопрос... Вопрос такой: Как это реализовать с помощью Qt (грамотно)? P.S. Примерчик бы.. С уважением, Алексей! |
Сообщ.
#2
,
|
|
|
Если речь идет о кроссплатформенном способе, то в dll надо вписать функции примерно такого вида:
extern "C" MyClassInterface* createMyClassInstance() { return new MyClass(); } Соответственно в своем приложении ты подцепляешь эту библиотеку (через dlopen/LoadLibrary или динамической линковкой -- это как больше нравится) и просто вызываешь createMyClassInstance. Предполагается, что MyClass унаследован от MyClassInterface. |
Сообщ.
#3
,
|
|
|
Вот вот по поводу унаследован. Если мой класс не наследован не от чего то, нужно заголовочный файл ещё подключать?
А если скажем мой класс будет наследником QObject и я к нему ещё добавлю методы, то заголовочный файл так же подключать надо? И ещё, можно ли каким либо образом использовать только dll, без хидера? |
Сообщ.
#4
,
|
|
|
Цитата Olimpik @ Если мой класс не наследован не от чего то, нужно заголовочный файл ещё подключать? Конечно, но это при условии (см ниже). Цитата Olimpik @ И ещё, можно ли каким либо образом использовать только dll, без хидера? Если твой класс наследуется от какого-либо базового интерфейса и тебе не нужно вызывать специфические методы, которые есть только в твоем классе, то хидер тебе не нужен, т. к. ты будешь вызывать виртуальные методы, объявленные в родительском классе, которые ты переопределил как надо. Если ты изменил интерфейс и тебе надо воспользоваться измененным интерфейсом, то без хидеров тут никак. Цитата Olimpik @ А если скажем мой класс будет наследником QObject и я к нему ещё добавлю методы, то заголовочный файл так же подключать надо? Если ты будешь вызывать только те методы, которые уже содержит QObject, то не надо, в противном случае без хидера никак. |
Сообщ.
#5
,
|
|
|
Ok. Буду пробывать...
О результатах сообщу... Добавлено Вот что у меня получилось: // Lib // // dynlib.h ////////////////////////////////////////// #include <qt.h> class Q_EXPORT MyClass { public: MyClass(); ~MyClass(); public: char* getTitle(); }; Q_EXTERN_C Q_EXPORT MyClass* getMyClass() { return new MyClass; } // dynlib.cpp ////////////////////////////////////////// #include "dynlib.h" MyClass::MyClass() {} MyClass::~MyClass() {} char* MyClass::getTitle() { return "I'm Class MyClass"; } // programm // main.cpp //////////////////////////////////////////////// ... #include "dynlib.h" //---------------------------------------------------------------------- int main (int argc, char** argv) { ... QLibrary lib(QDir::current().absPath() + "/libdynlib"); lib.load(); if (!lib.isLoaded()){lbl.setText("Library not Load");} typedef MyClass* (*Fct)(); Fct fct = (Fct)(lib.resolve("getMyClass")); if(fct){ MyClass* myClass = fct(); lbl.setText("<center><b>"+ QString(myClass->getTitle()) +"</b></center>"); } lib.unload(); ... return app.exec(); } bash-3.00$ make g++ -c -pipe -Wall -W -O2 -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT -I/usr/lib/qt/mkspecs/default -I. -I/usr/lib/qt/include -I.ui/ -I.moc/ -o .obj/main.o main.cpp main.cpp:35:2: warning: no newline at end of file g++ -Wl,-rpath,/usr/lib/qt/lib -o main .obj/main.o -L/usr/lib/qt/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm .obj/main.o(.text+0x15): In function `getMyClass': : undefined reference to `MyClass::MyClass[in-charge]()' .obj/main.o(.text+0x246): In function `main': : undefined reference to `MyClass::getTitle()' collect2: ld returned 1 exit status make: *** [main] Ошибка 1 // Errors ////////////////////////////////// Врозумите!!! |
Сообщ.
#6
,
|
|
|
Просто у тебя в dynlib.h описан не интерфейс абстрактного класса, а конкретный класс и gcc справедливо ругается на то, что не может найти функций, которые у тебя лежат в .so.
Сделать можно, например, так: // dynlib.h ////////////////////////////////////////// #include <qt.h> /* Абстрактный интерфейс */ class Q_EXPORT MyClassInterface { public: virtual ~MyClassInterface() {}; public: virtual char* getTitle() = 0; }; typedef MyClassInterface* (*getInstanceProc)(); В .so вписываешь #include "dynlib.h" class MyClass : public MyClassInterface { /* Реализовываешь все что надо */ public: virtual char *getTitle() {.......} }; Q_EXTERN_C Q_EXPORT MyClassInterface* getMyClass() { return new MyClass; } И в main: // ...... getInstanceProc fct = (getInstanceProc)(lib.resolve("getMyClass")); MyClassInstance = fct(); //..... P. S. я сразу что-то определение fct не заметил, поэтому getInstance приплел. Можно Fct оставить. |
Сообщ.
#7
,
|
|
|
Ура!!!!
Всё зароботала!!! благодарен!!! Вот конечный результат, вдруг кому пригодиться: Весь пример в трёх файла: ================================================ Библиотека | исходники: dynlib.h, dynlib.cpp | результат: libdynlib.so Тестовая прога | исходники: main.cpp | результат: main OS - Linux ================================================= ------------------------------------------------------- dynlib.h ------------------------------------------------------- #include <qt.h> /* Абстрактный интерфейс */ class Q_EXPORT MyClassInterface { public: virtual ~MyClassInterface() {}; public: virtual char* getTitle() = 0; }; ------------------------------------------------------- dynlib.cpp ------------------------------------------------------- #include "dynlib.h" class MyClass : public MyClassInterface { public: virtual char *getTitle() {return "I'm MyClass";} }; Q_EXTERN_C Q_EXPORT MyClassInterface* getMyClass() { return new MyClass(); } ------------------------------------------------------- main.cpp ------------------------------------------------------- #include <qapplication.h> #include <qdir.h> #include <qlabel.h> #include <qlibrary.h> #include <qstring.h> #include "dynlib.h" //---------------------------------------------------------------------- int main (int argc, char** argv) { QApplication app(argc, argv); QLabel lbl("", 0); QLibrary lib(QDir::current().absPath() + "/libdynlib"); lib.load(); if (!lib.isLoaded()){lbl.setText("Library not Load");} else {lbl.setText("Library not support this method");} typedef MyClassInterface* (*Fct)(); Fct fct = (Fct)(lib.resolve("getMyClass")); if(fct){ MyClassInterface* myClass = fct(); lbl.setText("<center><b>"+ QString(myClass->getTitle()) +"</b></center>"); } lib.unload(); app.setMainWidget(&lbl); lbl.resize(200,100); lbl.move(350,250); lbl.show(); return app.exec(); } Вроде всё... |