crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Как вызвать из плагина функцию приложения?
mva
  опции профиля:
сообщение 17.9.2010, 22:03
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 104
Регистрация: 15.3.2009
Из: Киров
Пользователь №: 615

Спасибо сказали: 3 раз(а)




Репутация:   0  


Добрый день!

Никак не могу найти в документации описание того, как правильно из плагина вызывать метод класса основного приложения. У меня выдается сообщение об ошибке "...: symbol lookup error: ... : undefined symbol: ... ". Может кто подскажет как это делается или где искать?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 18.9.2010, 0:33
Сообщение #2


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Ну, видимо, у меня используется подобная архитектура.
Т.е. есть некий функционал который используется как в основном приложении так и в плагинах. Сначала эти файлы у меня участвовали в компиляции как основного приложения так и плагинов. Т.е. происходило некое дублирование. И никаких проблем с этим нет, пока нет статических полей, ну или просто каких то общи данных, разделяемых между приложением и плагинами. Сейчас общий код у меня вынесен в отдельную разделяемую библиотеку, которая уже и используется всеми кто в ней заинтересован. Это мне кажется оптимальным вариантом.

В качестве еще одного варианта могу предложить GCC visibility (тык тык тык)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 18.9.2010, 8:44
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


если я правильно понимаю происходящее, то проблема в том, что некие классы в приложении и в библиотеке, должны взаимодействовать не напрямую, а через абстрактный интерфейсный класс (с истинно виртуальными методами).
На мой взгляд это единственный способ сказать линкеру, что реализации метода нет и не нужно её пытаться искать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 20.9.2010, 11:05
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(mva @ 17.9.2010, 23:03) *
Никак не могу найти в документации описание того, как правильно из плагина вызывать метод класса основного приложения. У меня выдается сообщение об ошибке "...: symbol lookup error: ... : undefined symbol: ... ". Может кто подскажет как это делается или где искать?


Вероятно можно передавать указатель на нужный объект через специальный метод, который объявить в плагине, типа setApplicationObject(QObject*). Приложение при подгрузке плагинов будет передавать в этот метод указатель на нужный объект. А там уже можно будет и через сигналы общаться.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 20.9.2010, 12:28
Сообщение #5


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


Думаю, правльно былобы иметь некий интерфейс, реализованый на уровне приложения, и передавть в плагин указатель на интерфейс.
Все остальные подходы имеют свои недостатки и усиливают бинарную связь между плагином и приложением.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mva
  опции профиля:
сообщение 21.9.2010, 8:42
Сообщение #6


Участник
**

Группа: Участник
Сообщений: 104
Регистрация: 15.3.2009
Из: Киров
Пользователь №: 615

Спасибо сказали: 3 раз(а)




Репутация:   0  


Цитата(wiz29 @ 20.9.2010, 13:28) *
Думаю, правльно былобы иметь некий интерфейс, реализованый на уровне приложения, и передавть в плагин указатель на интерфейс.
Все остальные подходы имеют свои недостатки и усиливают бинарную связь между плагином и приложением.


Этот вариант мне показался самым простым. Если под интерфейсом понимается простой класс-прослойка, а не какой-либо специализированный класс Qt, то я вчера попробовал сделать такой интерфейс. Результат тот же. Точно также плагин не находит методы-члены этого класса.


Цитата(SABROG @ 20.9.2010, 12:05) *
Вероятно можно передавать указатель на нужный объект через специальный метод, который объявить в плагине, типа setApplicationObject(QObject*). Приложение при подгрузке плагинов будет передавать в этот метод указатель на нужный объект. А там уже можно будет и через сигналы общаться.


Да, у меня так и сделано. Проблема только в том, что через механизм сигналов-слотов нельзя вернуть данные.

Цитата(Litkevich Yuriy @ 18.9.2010, 9:44) *
На мой взгляд это единственный способ сказать линкеру, что реализации метода нет и не нужно её пытаться искать.


Сообщение об ошибке появляется не на этапе линковки, а во время выполнения программы в момент обращения к функции основного приложения в плагине.

Цитата(igor_bogomolov @ 18.9.2010, 1:33) *
Ну, видимо, у меня используется подобная архитектура.
Т.е. есть некий функционал который используется как в основном приложении так и в плагинах. Сначала эти файлы у меня участвовали в компиляции как основного приложения так и плагинов. Т.е. происходило некое дублирование. И никаких проблем с этим нет, пока нет статических полей, ну или просто каких то общи данных, разделяемых между приложением и плагинами. Сейчас общий код у меня вынесен в отдельную разделяемую библиотеку, которая уже и используется всеми кто в ней заинтересован. Это мне кажется оптимальным вариантом.

В качестве еще одного варианта могу предложить GCC visibility (тык тык тык)


Я так понял, что GCC visibility имеет смысл, если создается библиотека. Выделение искомого кода в библиотеку затруднительно по причине большой связности с остальным кодом. Это везде перед вызовом функции нужно вставлять код для поиска данной функции в библиотеке. Хотелось бы сделать по-проще.

Пока думаю остановиться на таком варианте: после загрузки плагина "начинить" его необходимыми для его работы данными, чтобы он сам не обращался за ними в основную программу. Но вопрос вызова функций из основного приложения все же остается открытым.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 21.9.2010, 9:33
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


приведи код интерфейса и код использования в плагине. Как ты вызываешь метод?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 21.9.2010, 11:15
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(mva @ 21.9.2010, 9:42) *
Но вопрос вызова функций из основного приложения все же остается открытым.

Если ты можешь передавать указатель на QObject, то передавай указатель на "void *" и приводи его к нужному интерфейсу.

Через механизм сигналов-слотов данные вернуть можно через схему: сигнал_запрос - слот - сигнал_ответ. Если нужно дождаться ответного сигнала, то можно QEventLoop использовать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 21.9.2010, 11:26
Сообщение #9


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Написал тестовый пример имитирующий проблему (переделанный стандартный пример из поставки Qt). Сам пример, конечно, не самый элегантный, но все проблемы и возможные способы решения он показывает.

Сам пример в приложении. Предлагаю его в том виде, когда он даст ошибку на этапе исполнения, как раз то о чем говорит mva

Я расширил стандартный пример неким классом SharedUtils который находится в файле shared_utils.* Этот код компилируется вместе с приложением.
А теперь возникает ситуация, что этот функционал, который предоставляет SharedUtils, необходим не только приложению, но и плагину. Тот код, который я приложил, удачно скомпилируется (и приложение даже запустится), но при нажатии на кнопку произойдет ошибка, и в общем понятно почему.

Я ранее еще предложил три пути решения этой проблемы
1. Включить shared_utils.* в компиляцию плагина. Модифицируем plugin pro
HEADERS         = echoplugin.h \
                  ../echowindow/shared_utils.h
SOURCES         = echoplugin.cpp \
                  ../echowindow/shared_utils.cpp
И, ву а ля, все работает. Но это не хорошо. Т.о. мы просто продублировали функционал. Если у нас появятся статические данные, будут проблемы, т.к. статическая переменная в приложении и в плагине - это две совершенно разные переменные.

2. Выделить общий код в разделяемую библиотеку (.dll/.so). (У меня в проекте сделано именно так)

3. GCC visibility. Добавляем в файл проекта приложения следущую строку
QMAKE_LFLAGS += -Wl,-export-dynamic -fvisibility=hidden


И помечаем класс следующим образом
class __attribute__ ((visibility ("default"))) SharedUtils
{
    ....
}
Всё, этого вполне достаточно.
Прикрепленные файлы
Прикрепленный файл  echoplugin.zip ( 5.11 килобайт ) Кол-во скачиваний: 122
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mva
  опции профиля:
сообщение 21.9.2010, 11:49
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 104
Регистрация: 15.3.2009
Из: Киров
Пользователь №: 615

Спасибо сказали: 3 раз(а)




Репутация:   0  


Извиняюсь, не указал важную деталь и возможно ввел в заблуждение: ошибка происходит в слоте, который является элементом плагина. В остальной части плагина вызов функций основного приложения происходит корректно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


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




RSS Текстовая версия Сейчас: 24.4.2024, 13:29