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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: И снова о динамических библиотеках......  (Прочитано 5622 раз)
wertklop
Гость
« : Февраль 26, 2011, 21:07 »

Всем привет!

После долгих исканий в инете, прочтения доков, а также здесь на форуме, что то нашёл дря решения своего вопроса, но не до конца.
Суть задачки вот в чём:
Для примера, хотелось бы, чтобы при старте приложения загружалась библиотека (*.so) и делала необходимые действия.
Исходники приложения:
mainwindow.h
Код:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "interface.h" //без этого не работает, а надо без него
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
#endif // MAINWINDOW_H
interface.h
Код:
#ifndef INTERFACE_H
#define INTERFACE_H
class MyModuleInterface
{
public:
    virtual ~MyModuleInterface() {}
    virtual QString run() = 0;
};
Q_DECLARE_INTERFACE(MyModuleInterface, "mywww.My.MyModuleInterface/1.0")
#endif // INTERFACE_H
mainwindow.cpp
Код:
#include "mainwindow.h"
#include <QtGui>

MainWindow::MainWindow()
{
QPluginLoader loader( ".../libplugin.so" );
    if ( !loader.load() )
    {
        MainWindow::setWindowTitle("This is not Qt plugin or plugin not match out Qt Libraries" );
      return;
    }
    MyModuleInterface * i = qobject_cast<MyModuleInterface*>( loader.instance() );
    if ( !i )
    {
      MainWindow::setWindowTitle( "This is not plugin for interface MyInterface" );
      return;
    }
    MainWindow::setWindowTitle( i->run());
main.cpp
Код:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
project.pro
Код:
QT       += core gui
TARGET = project
TEMPLATE = app
SOURCES += main.cpp mainwindow.cpp
HEADERS  += mainwindow.h interface.h

Исходники библиотеки:
interface.h
Код:
#ifndef INTERFACE_H
#define INTERFACE_H
class MyModuleInterface
{
public:
    virtual ~MyModuleInterface() {}
    virtual QString run() = 0;
};
Q_DECLARE_INTERFACE(MyModuleInterface, "mywww.My.MyModuleInterface/1.0")
#endif // INTERFACE_H
plugin.h
Код:
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QObject>
#include "interface.h"
class MyModulePlugin : public QObject, public MyModuleInterface
{
    Q_OBJECT
    Q_INTERFACES(MyModuleInterface)
public:
    QString run() { return QString("Ready!"); };
};
#endif // PLUGIN_H
plugin.cpp
Код:
#include <QtGui>
#include "plugin.h"
Q_EXPORT_PLUGIN2(mymoduleplugin, MyModulePlugin)
plugin.pro
Код:
TEMPLATE = lib
CONFIG += plugin
VERSION = 1.0.0
DEFINES += D_SHARED_LIB
TARGET = plugin
HEADERS += interface.h plugin.h
SOURCES += plugin.cpp

Т.е. у нас получилось, что interface.h, с конкретными определёнными методами, и в библиотеке, и в приложении, иначе не работает.
за основу брал примеры http://www.prog.org.ru/topic_8259_0.html, http://www.prog.org.ru/index.php?topic=4120.msg18558#msg18558 и http://www.prog.org.ru/index.php?topic=8357.msg45637#msg45637, http://www.e-reading.org.ua/bookreader.php/136170/Blanshet_-_QT_4%3A_programmirovanie_GUI_na_S%2B%2B.html(20 глава). Но хотелось бы средствами Qt, если это воможно, не определять явно интерфейс в приложении(потому как это плохо), а просто загрузить библиотеку, вызвать нужный нам метод(или что-то другое), а потом, если надо, то выгрузить библиотеку. Короче, что то подобное расписано на http://www.ibm.com/developerworks/ru/library/l-dynamic-libraries/index.html. Повторю, хотелось бы реализовать именно стрествами Qt, если это возможно.
Записан
Hronom
Гость
« Ответ #1 : Февраль 27, 2011, 00:07 »

Посмотрите в сторону QLibrary::resolve я сам не пробовал, но вроде там написано как можно дёргать функции из либы без использования интерфейса.
Записан
wertklop
Гость
« Ответ #2 : Февраль 27, 2011, 01:11 »

Удалил из приложения interface.h
Попробовал вот так, как в Аssistant'е:
Код:
typedef Qstring (*MyPrototype)();
     MyPrototype myFunction = (MyPrototype) QLibrary::resolve(".../libplugin.so", "run");
     if (myFunction) MainWindow::setWindowTitle(myFunction());
Программа компилируется без ошибок, но метод run() даже не выполняется. Пробовал в библиотеке переопределить метод на тип void, а в нём просто запись в файл производил и ничего не возвращал, но всё равно без изменений, текстовый файл даже не создавался, значит run() даже не запускался. Подскажите, как быть?
Записан
Hronom
Гость
« Ответ #3 : Февраль 27, 2011, 01:32 »

Удалил из приложения interface.h
Попробовал вот так, как в Аssistant'е:
Код:
typedef Qstring (*MyPrototype)();
     MyPrototype myFunction = (MyPrototype) QLibrary::resolve(".../libplugin.so", "run");
     if (myFunction) MainWindow::setWindowTitle(myFunction());
Программа компилируется без ошибок, но метод run() даже не выполняется. Пробовал в библиотеке переопределить метод на тип void, а в нём просто запись в файл производил и ничего не возвращал, но всё равно без изменений, текстовый файл даже не создавался, значит run() даже не запускался. Подскажите, как быть?

Судя по асисту нужно ещё произвести махинацию над функцией в либе что-то вроде этого:
Код:
extern "C" MY_EXPORT int avg(int a, int b)
 {
     return (a + b) / 2;
 }
и в заголовке там где описывается функция вставить такую конструкцию:
Код:
#ifdef Q_WS_WIN
 #define MY_EXPORT __declspec(dllexport)
 #else
 #define MY_EXPORT
 #endif
« Последнее редактирование: Февраль 27, 2011, 01:34 от Hronom » Записан
wertklop
Гость
« Ответ #4 : Февраль 27, 2011, 01:58 »

Возможно это прокатило, но мне надо в linux, поэтому у меня пишет ".../plugin.h:23: error: expected unqualified-id before string constant" в строке "extern "C" MY_EXPORT void run()". Усли убрать определение MY_EXPORT, то всё равно та же ошибка
Записан
Hronom
Гость
« Ответ #5 : Февраль 27, 2011, 02:21 »

Вот правильные исходники
plugin.h
Код:
#ifndef PLUGIN_H
#define PLUGIN_H

#ifdef Q_WS_WIN
 #define MY_EXPORT __declspec(dllexport)
 #else
 #define MY_EXPORT
 #endif

#include <QObject>
#include <QString>
class MyModulePlugin : public QObject
{
    Q_OBJECT
public:
    extern "C" MY_EXPORT QString run() { return QString("Ready!"); };
};
#endif // PLUGIN_H
plugin.cpp
Код:
#include <QtGui>
Q_EXPORT_PLUGIN2(mymoduleplugin, MyModulePlugin)

Если не поможет могу пошарить в проекте(залейте его куда-то) ибо мне тоже эта тема интересна, моя программа сейчас работает на интерфейсах...
« Последнее редактирование: Февраль 27, 2011, 02:24 от Hronom » Записан
wertklop
Гость
« Ответ #6 : Февраль 27, 2011, 02:30 »

Hronom , ты проверял их? я привёл к виду, как ты написал, всё равно та же ошибка. и ещё вопрос, а куда ты интерфейс подевал, он что не нужен разве???
Записан
Hronom
Гость
« Ответ #7 : Февраль 27, 2011, 02:32 »

Hronom , ты проверял их? я привёл к виду, как ты написал, всё равно та же ошибка. и ещё вопрос, а куда ты интерфейс подевал, он что не нужен разве???
Интерфейс в модуле не нужен если ты через него не работаешь, залей архивчик с исходниками куда-то)))
Записан
wertklop
Гость
« Ответ #8 : Февраль 27, 2011, 02:40 »

тут в архиве проекты библиотеки и приложения. к коментариях есть пробная реализация Сишной ф-ции(с сайта IBM)
« Последнее редактирование: Февраль 27, 2011, 02:47 от wertklop » Записан
Hronom
Гость
« Ответ #9 : Февраль 27, 2011, 03:45 »

Вобщем, получилось... но вызывать с либы удалось только функцию, но не метод класса.
Записан
wertklop
Гость
« Ответ #10 : Февраль 27, 2011, 04:06 »

Ну спасибо хоть и на этом Улыбающийся
только вот у меня несколько вопросов, просвяти:
1)xLibrary->setLoadHints(QLibrary::ResolveAllSymbolsHint); - почему ты её закомментил и зачем она нужна?


Кстати, пробовал run2() сделать не от типа int, а qt'шным типом(QObject), компилятор выдал, что невозможно вызвать не скалярную ф-цию. Я так понимаю, что мы же экстерном вызываем ф-цию сишного типа, а в С вроде как нет ни объектов, ни чего-то подобного......Можно сделать и так, но опять же с типами, которые поддерживат С:
Код:
extern "C" MY_EXPORT int run2()
{
    MyModulePlugin*myPlugin = new MyModulePlugin;
    int result = myPlugin->run();
    qDebug()<<result;//12
    return 13;               //13
}
« Последнее редактирование: Февраль 27, 2011, 05:24 от wertklop » Записан
Hronom
Гость
« Ответ #11 : Февраль 27, 2011, 14:10 »

Ну спасибо хоть и на этом Улыбающийся
только вот у меня несколько вопросов, просвяти:
1)xLibrary->setLoadHints(QLibrary::ResolveAllSymbolsHint); - почему ты её закомментил и зачем она нужна?


Кстати, пробовал run2() сделать не от типа int, а qt'шным типом(QObject), компилятор выдал, что невозможно вызвать не скалярную ф-цию. Я так понимаю, что мы же экстерном вызываем ф-цию сишного типа, а в С вроде как нет ни объектов, ни чего-то подобного......Можно сделать и так, но опять же с типами, которые поддерживат С:
Код:
extern "C" MY_EXPORT int run2()
{
    MyModulePlugin*myPlugin = new MyModulePlugin;
    int result = myPlugin->run();
    qDebug()<<result;//12
    return 13;               //13
}
У меня запахало с QString'ом и QObject* вместо int... ниже прикреплены исходники) Я так понимаю и свои классы можно тоже гонять...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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