Как вызвать из плагина функцию приложения? |
Здравствуйте, гость ( Вход | Регистрация )
Как вызвать из плагина функцию приложения? |
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 |
Никак не могу найти в документации описание того, как правильно из плагина вызывать метод класса основного приложения. У меня выдается сообщение об ошибке "...: 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 |
Думаю, правльно былобы иметь некий интерфейс, реализованый на уровне приложения, и передавть в плагин указатель на интерфейс. Все остальные подходы имеют свои недостатки и усиливают бинарную связь между плагином и приложением. Этот вариант мне показался самым простым. Если под интерфейсом понимается простой класс-прослойка, а не какой-либо специализированный класс Qt, то я вчера попробовал сделать такой интерфейс. Результат тот же. Точно также плагин не находит методы-члены этого класса. Вероятно можно передавать указатель на нужный объект через специальный метод, который объявить в плагине, типа setApplicationObject(QObject*). Приложение при подгрузке плагинов будет передавать в этот метод указатель на нужный объект. А там уже можно будет и через сигналы общаться. Да, у меня так и сделано. Проблема только в том, что через механизм сигналов-слотов нельзя вернуть данные. На мой взгляд это единственный способ сказать линкеру, что реализации метода нет и не нужно её пытаться искать. Сообщение об ошибке появляется не на этапе линковки, а во время выполнения программы в момент обращения к функции основного приложения в плагине. Ну, видимо, у меня используется подобная архитектура. Т.е. есть некий функционал который используется как в основном приложении так и в плагинах. Сначала эти файлы у меня участвовали в компиляции как основного приложения так и плагинов. Т.е. происходило некое дублирование. И никаких проблем с этим нет, пока нет статических полей, ну или просто каких то общи данных, разделяемых между приложением и плагинами. Сейчас общий код у меня вынесен в отдельную разделяемую библиотеку, которая уже и используется всеми кто в ней заинтересован. Это мне кажется оптимальным вариантом. В качестве еще одного варианта могу предложить 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 |
Но вопрос вызова функций из основного приложения все же остается открытым. Если ты можешь передавать указатель на 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 И, ву а ля, все работает. Но это не хорошо. Т.о. мы просто продублировали функционал. Если у нас появятся статические данные, будут проблемы, т.к. статическая переменная в приложении и в плагине - это две совершенно разные переменные. 2. Выделить общий код в разделяемую библиотеку (.dll/.so). (У меня в проекте сделано именно так) 3. GCC visibility. Добавляем в файл проекта приложения следущую строку
И помечаем класс следующим образом Всё, этого вполне достаточно.
Прикрепленные файлы
|
|
|
mva |
21.9.2010, 11:49
Сообщение
#10
|
Участник Группа: Участник Сообщений: 104 Регистрация: 15.3.2009 Из: Киров Пользователь №: 615 Спасибо сказали: 3 раз(а) Репутация: 0 |
Извиняюсь, не указал важную деталь и возможно ввел в заблуждение: ошибка происходит в слоте, который является элементом плагина. В остальной части плагина вызов функций основного приложения происходит корректно.
|
|
|
Текстовая версия | Сейчас: 19.12.2024, 23:56 |