На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Класс в динамичиской библиотеке(so, dll) , с использованием Qt
    Здравствуте!

    Что делаю: мне надо написать динамически подгружаемую библиотеку(so или dll) в котором будет описан некий класс, затем, подгрузив библиотеку, создать экземпляр класса, хранящегося в библиотеке, и работать с ним.

    Могу сказать, что попытки с моей стороны были! Точнее библиотеку с классом я написал(вроде как, т.е. она компилится и создаётся без проблем), но вот как получить правилино создать экземпляр класса вопрос...

    Вопрос такой: Как это реализовать с помощью Qt (грамотно)?

    P.S. Примерчик бы..
    С уважением, Алексей!
      Если речь идет о кроссплатформенном способе, то в dll надо вписать функции примерно такого вида:
      ExpandedWrap disabled
        extern "C" MyClassInterface* createMyClassInstance() {
          return new MyClass();
        }

      Соответственно в своем приложении ты подцепляешь эту библиотеку (через dlopen/LoadLibrary или динамической линковкой -- это как больше нравится) и просто вызываешь createMyClassInstance.
      Предполагается, что MyClass унаследован от MyClassInterface.
      Сообщение отредактировано: linuxfan -
        Вот вот по поводу унаследован. Если мой класс не наследован не от чего то, нужно заголовочный файл ещё подключать?

        А если скажем мой класс будет наследником QObject и я к нему ещё добавлю методы, то заголовочный файл так же подключать надо?

        И ещё, можно ли каким либо образом использовать только dll, без хидера?
          Цитата Olimpik @
          Если мой класс не наследован не от чего то, нужно заголовочный файл ещё подключать?

          Конечно, но это при условии (см ниже).
          Цитата Olimpik @
          И ещё, можно ли каким либо образом использовать только dll, без хидера?

          Если твой класс наследуется от какого-либо базового интерфейса и тебе не нужно вызывать специфические методы, которые есть только в твоем классе, то хидер тебе не нужен, т. к. ты будешь вызывать виртуальные методы, объявленные в родительском классе, которые ты переопределил как надо.
          Если ты изменил интерфейс и тебе надо воспользоваться измененным интерфейсом, то без хидеров тут никак.
          Цитата Olimpik @
          А если скажем мой класс будет наследником QObject и я к нему ещё добавлю методы, то заголовочный файл так же подключать надо?

          Если ты будешь вызывать только те методы, которые уже содержит QObject, то не надо, в противном случае без хидера никак.
            Ok. Буду пробывать...

            О результатах сообщу...

            Добавлено
            Вот что у меня получилось:

            ExpandedWrap disabled
              // 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
              //////////////////////////////////




            Врозумите!!!
              Просто у тебя в dynlib.h описан не интерфейс абстрактного класса, а конкретный класс и gcc справедливо ругается на то, что не может найти функций, которые у тебя лежат в .so.
              Сделать можно, например, так:
              ExpandedWrap disabled
                // dynlib.h
                //////////////////////////////////////////
                #include <qt.h>
                /* Абстрактный интерфейс */
                class  Q_EXPORT  MyClassInterface
                {
                public:
                    virtual ~MyClassInterface() {};
                public:
                    virtual char* getTitle() = 0;
                };
                 
                typedef MyClassInterface* (*getInstanceProc)();


              В .so вписываешь
              ExpandedWrap disabled
                #include "dynlib.h"
                 
                class MyClass : public MyClassInterface {
                  /* Реализовываешь все что надо */
                  public:
                    virtual char *getTitle() {.......}
                };
                 
                Q_EXTERN_C Q_EXPORT MyClassInterface* getMyClass()
                {
                    return new MyClass;
                }


              И в main:
              ExpandedWrap disabled
                // ......
                getInstanceProc fct = (getInstanceProc)(lib.resolve("getMyClass"));
                MyClassInstance = fct();
                //.....

              P. S. я сразу что-то определение fct не заметил, поэтому getInstance приплел. Можно Fct оставить.
                :D Ура!!!!

                Всё зароботала!!! благодарен!!!

                Вот конечный результат, вдруг кому пригодиться:

                Весь пример в трёх файла:
                ================================================
                Библиотека | исходники: dynlib.h, dynlib.cpp
                | результат: libdynlib.so

                Тестовая прога | исходники: main.cpp
                | результат: main

                OS - Linux
                =================================================

                -------------------------------------------------------
                dynlib.h
                -------------------------------------------------------
                ExpandedWrap disabled
                   #include <qt.h>
                   
                  /* Абстрактный интерфейс */
                  class  Q_EXPORT  MyClassInterface
                  {
                  public:
                      virtual ~MyClassInterface() {};
                  public:
                      virtual char* getTitle() = 0;
                  };


                -------------------------------------------------------
                dynlib.cpp
                -------------------------------------------------------
                ExpandedWrap disabled
                  #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
                -------------------------------------------------------
                ExpandedWrap disabled
                  #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();
                  }


                Вроде всё...
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0305 ]   [ 16 queries used ]   [ Generated: 15.04.24, 21:28 GMT ]