Russian Qt Forum

Qt => Общие вопросы => Тема начата: DarkPhoenix от Май 04, 2010, 14:34



Название: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 04, 2010, 14:34
имеется класс с public методами. при попытке вызвать метод из основного приложения - работает
при попытке вызвать public метод, по указателю, из плагина, загруженного при помощи QPluginLoader - не находит public метод. но прямое обращение к public указателю на виджет работает.
т.е. если по указателю получать объект - работает, если по указателю получать объект используя обертку в виде public функция - не работает.

интерфейс:
Код:
class PluginInterface
{
public:
    virtual void version();
    virtual void path();
    virtual void setMainWnd(MainWindow * prmVal);
};

Код:
class PluginManager
{
public:
    explicit PluginManager();
    static PluginManager* instance();

    void loadPlugins();
    void setMainWnd(MainWindow * prmVal);
private:
    QList<PluginInterface *> plugins;
    MainWindow * mainWnd;

private:
    static PluginManager* _self;
};

Код:
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void echo();

    QWebView * view;

    QWebView * getWebView();

};

инициализация менеджера, установка указателя на текущую форму (MainWindow)
Код:
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    view = new QWebView;
    view->load(QUrl("http://ya.ru"));

    setCentralWidget(view);

    PluginManager * pluginmanager = PluginManager::instance();
    pluginmanager->setMainWnd(this);
    pluginmanager->loadPlugins();
}

QWebView * MainWindow::getWebView()
{
    return view;
}

загрузка плагинов
Код:
            gamePlugin = qobject_cast<PluginInterface *>(plugin);
            if (gamePlugin)
            {
                plugins << gamePlugin;
                gamePlugin->setMainWnd(mainWnd);
                gamePlugin->version();
                QMessageBox::information(0,"Plugin manager",fileName);
            }
-----
плагин:

Код:
void TestPlugin2::version()
{
    mainWnd->echo(); // НЕ работает: release/testplugin2.o:testplugin2.cpp::-1: error: undefined reference to `MainWindow::echo()'
    // QWebView * view = mainWnd->getWebView(); // НЕ работает: release/testplugin2.o:testplugin2.cpp::-1: error: undefined reference to `MainWindow::getWebView()'
    QWebView * view = mainWnd->view; // РАБОТАЕТ
    if (view != 0)
    {
        view->load(QUrl("http://yandex.ru"));
    }
    QMessageBox::information(0,"test plugin 2","version");
}

прилагаю исходник проекта.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Sancho_s_rancho от Май 04, 2010, 18:14
1) У вас в конструкторе главного окна создается PluginManager и в нем экземпляр класса плагина,  плагин в свою очередь вызывает открытый метод главного окна, т.е. главное окно еще не создано до конца, а вы его публичные методы из другого класса дергаете. Нехорошо
2) В интерфейсе плагинов надо включить #include <QtPlugin>. Во всяком случае так говорит документация.
3)Методы класса интерфейса можно объявить чисто виртуальными (=0).
4)Деструктор в интерфейсном классе объявите виртуальным.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: ритт от Май 05, 2010, 10:03
а я вчера поленился тратить время :)

@Sancho_s_rancho, зачёт


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 05, 2010, 12:27
1) У вас в конструкторе главного окна создается PluginManager и в нем экземпляр класса плагина,  плагин в свою очередь вызывает открытый метод главного окна, т.е. главное окно еще не создано до конца, а вы его публичные методы из другого класса дергаете. Нехорошо
2) В интерфейсе плагинов надо включить #include <QtPlugin>. Во всяком случае так говорит документация.
3)Методы класса интерфейса можно объявить чисто виртуальными (=0).
4)Деструктор в интерфейсном классе объявите виртуальным.

п.1. вынес загрузку плагина в main.cpp (после w.show();) согласен с первоначальной кривизной.
п.2. включил в интерфейс и в реализацию плагина (странно, не заметил это в документации)
п.3. пробовал делать так, не помогло. вернул.
п.4. в интерфейсе объявил: virtual ~PluginInterface() = 0;
в плагине объявил и создал заглушку: ~TestPlugin2();
результат: release/testplugin2.o:testplugin2.cpp::-1: error: undefined reference to `PluginInterface::~PluginInterface()'


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: BRE от Май 05, 2010, 12:36
4)Деструктор в интерфейсном классе объявите виртуальным.

п.4. в интерфейсе объявил: virtual ~PluginInterface() = 0;
Так не надо.  :)
Лучше так:
virtual ~PluginInterface() {}


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 05, 2010, 12:46
Цитировать
Так не надо.  :)
Лучше так:
virtual ~PluginInterface() {}

Спасибо помогло :)

но: release/testplugin2.o:testplugin2.cpp::-1: error: undefined reference to `MainWindow::getWebView()'
по прежнему есть :(
может как-то иначе оформить метод?

Код:
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void echo();
    MainWindow * self();
    QWebView * view;
    QWebView * getWebView();
};


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Sancho_s_rancho от Май 05, 2010, 14:15
Суперприз в студию Код приложи обновленный!


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 05, 2010, 14:18
обновил исходник


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 24, 2010, 11:49
вопрос по прежнему открыт :(


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Авварон от Май 24, 2010, 13:13
ну вполне логично - у вас главное окно в ДРУГОМ модуле компиляции => его методы из плагна вызывать нельзя (в плагине этих функций нет).


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Май 24, 2010, 15:53
при этом widgets доступны....
странно как-то сделано.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Июль 23, 2010, 17:50
Повозился с QPluginManager
пришел к выводу что для реализации плагинов более чем "hello world" функционал не пригоден.
Работать с параметрами в виде базовых объектов QT очень не интересно, не функционально.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Авварон от Июль 23, 2010, 19:04
qobject_cast мы не проходили?


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: ритт от Июль 23, 2010, 20:34
каст-кастом, но что толку, если он из плагина в приватную секцию лезет? /* ещё и функционал ему непригоден...:) */

@BW, а импорт/экспорт - это для чего, подскажи?


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Июль 24, 2010, 10:15
каст-кастом, но что толку, если он из плагина в приватную секцию лезет? /* ещё и функционал ему непригоден...:) */

@BW, а импорт/экспорт - это для чего, подскажи?
пытался вызывать PUBLIC метод, а не PRIVATE
EXPORT - это скорее уже к реализации обычных dll, или ошибаюсь?

qobject_cast мы не проходили?
в моем случае это не нужно.

+ если у меня кривые руки - буду рад, если кто-то их выпрямит, например подправив приложенный мной исходник, для лучшего понимания.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Авварон от Июль 24, 2010, 12:51
вы не можете вызвать функцию из другого МОДУЛЯ, не линкуясь к нему.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Июль 24, 2010, 13:30
вы не можете вызвать функцию из другого МОДУЛЯ, не линкуясь к нему.
прошу показать на примере моего кода как это сделать.
либо на примере Вашего кода.


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: DarkPhoenix от Июль 29, 2010, 11:45
Тишина...


Название: Re: QPluginLoader + Указатель - не находит public методы
Отправлено: Авварон от Август 01, 2010, 19:22
в вашем случае - никак.
Оформляйте код, необходимый в плагинах в виде отдельной библиотеки (ака core.dll) и линкуйтесь к ней. Либо пересматривайте архитектуру (используйте сигналы/слоты или интерфейсы)