Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Общие вопросы _ Ни как не могу слинковать.

Автор: Гость_heiheshang_* 7.11.2009, 16:36

Проблема в следующем, ни как не могу слинковать код. В qtcreator есть библиотека libDuiEditor. Я ее подключаю к своему проекту. Код компилируется, но линковщик в упор не хочет видеть этот модуль.

undefined reference to `DuiEditor::Internal::DuiEditorPlugin::DuiEditorPlugin()

Может я чего-то не понимаю ?
DuiEditor::Internal::DuiEditorPlugin *plugin =new DuiEditor::Internal::DuiEditorPlugin();

Вот код самого модуля
#ifndef DUIEDITORPLUGIN_H
#define DUIEDITORPLUGIN_H

#include <extensionsystem/iplugin.h>

namespace TextEditor {
class TextFileWizard;
class TextEditorActionHandler;
} // namespace TextEditor

namespace DuiEditor {
namespace Internal {

class DuiEditorFactory;
class DuiCodeCompletion;
class ScriptEditor;

class DuiEditorPlugin : public ExtensionSystem::IPlugin
{
    Q_OBJECT

public:
    DuiEditorPlugin();
    virtual ~DuiEditorPlugin();

    // IPlugin
    bool initialize(const QStringList &arguments, QString *errorMessage = 0);
    void extensionsInitialized();

    static DuiEditorPlugin *instance()
    { return m_instance; }

    void initializeEditor(ScriptEditor *editor);

private:
    void registerActions();

    static DuiEditorPlugin *m_instance;

    typedef QList<int> Context;
    Context m_context;
    Context m_scriptcontext;

    TextEditor::TextFileWizard *m_wizard;
    DuiEditorFactory *m_editor;
    TextEditor::TextEditorActionHandler *m_actionHandler;
    DuiCodeCompletion *m_completion;
};

} // namespace Internal
} // namespace DuiEditor

#endif // DUIEDITORPLUGIN_H

Автор: SABROG 7.11.2009, 16:59

Покажи .pro файл.

Автор: Гость_heiheshang_* 7.11.2009, 17:08

Цитата(SABROG @ 7.11.2009, 16:59) *
Покажи .pro файл.

LIBS += -lDuiEditor

Вас этот момент интересует ?

Автор: frg10 8.11.2009, 4:06

Цитата(Гость_Гость_heiheshang_*_* @ 7.11.2009, 16:36) *
Может я чего-то не понимаю ?
DuiEditor::Internal::DuiEditorPlugin *plugin =new DuiEditor::Internal::DuiEditorPlugin();


Вроде инстансы плагинов не создаются вручную. Нужно использовать QPluginLoader. Вобщем смотри ассистант.
Еще можно попробовать добавить к описанию класса Q_DECL_EXPORT/IMPORT чтобы сделать его интерфейс видимым снаружи. Но при этом нужно будет пересобрать либу.

Автор: Гость_heiheshang_* 8.11.2009, 15:19

Цитата(frg10 @ 8.11.2009, 4:06) *
Цитата(Гость_Гость_heiheshang_*_* @ 7.11.2009, 16:36) *
Может я чего-то не понимаю ?
DuiEditor::Internal::DuiEditorPlugin *plugin =new DuiEditor::Internal::DuiEditorPlugin();


Вроде инстансы плагинов не создаются вручную. Нужно использовать QPluginLoader. Вобщем смотри ассистант.
Еще можно попробовать добавить к описанию класса Q_DECL_EXPORT/IMPORT чтобы сделать его интерфейс видимым снаружи. Но при этом нужно будет пересобрать либу.

Да руками не создаются, делаю так
QPluginLoader plugin("/usr/lib/libDuiEditor.so");
QObject *obj = qobject_cast<QObject *>(plugin.instance());
if (obj){
         qDebug() << "Загрузили";
         DuiEditorPlugin *dui = qobject_cast<DuiEditorPlugin *>(obj);
}

Получаем ошибку линковки
/usr/include/QtCore/qobject.h:443: undefined reference to `DuiEditor::Internal::DuiEditorPlugin::staticMetaObject'

Автор: frg10 8.11.2009, 17:40

ИМХО без правки исходников не обойтись. Дело в том, что если вы хотите использовать какой-то класс определенный в динамической библиотеке, этот класс должен из нее экспортироваться. Т.е. класс должен быть объявлен так:

class DUIEDITOR_EXPORT DuiEditorPlugin : public ExtensionSystem::IPlugin

Подробности в http://doc.crossplatform.ru/qt/en/4.5.0/sharedlibrary.html

Ну и пересобрать нужно будет этот плагин. И линковать нужно будет статически через -lDuiEditor.


А вообще, зачем вам доступ к классу DuiEditorPlugin? Если вам нужно его инициализировать, то нужно кастить его к ExtensionSystem::IPlugin. А доступ ко всем объектам, которые он предоставляет, осуществляется через ExtensionSystem::PluginManger.

Автор: Гость_heiheshang_* 8.11.2009, 19:11

Цитата(frg10 @ 8.11.2009, 17:40) *
ИМХО без правки исходников не обойтись. Дело в том, что если вы хотите использовать какой-то класс определенный в динамической библиотеке, этот класс должен из нее экспортироваться. Т.е. класс должен быть объявлен так:
class DUIEDITOR_EXPORT DuiEditorPlugin : public ExtensionSystem::IPlugin

Подробности в http://doc.crossplatform.ru/qt/en/4.5.0/sharedlibrary.html

Ну и пересобрать нужно будет этот плагин. И линковать нужно будет статически через -lDuiEditor.


А вообще, зачем вам доступ к классу DuiEditorPlugin? Если вам нужно его инициализировать, то нужно кастить его к ExtensionSystem::IPlugin. А доступ ко всем объектам, которые он предоставляет, осуществляется через ExtensionSystem::PluginManger.

Может сам класс мне и не нужен, главное получить его функционал,если подскажите как им воспользоваться буду благодарен.

Автор: frg10 8.11.2009, 23:11

Цитата(Гость_Гость_heiheshang_*_* @ 8.11.2009, 19:11) *
Может сам класс мне и не нужен, главное получить его функционал,если подскажите как им воспользоваться буду благодарен.


Я могу вам посоветовать подробнее разобраться с архитектурой QtCreator. Мне очень помог документ http://www.vcreatelogic.com/downloads/files/Writing-Qt-Creator-Plugins.pdf. Как понятно из названия, там описывается как писать собственные плагины, ну и параллельно разбирается архитектура. А дальше нужно просто брать исходники самого креатора и разбираться. :D Кстати, всем советую, потому что сделано все очень красиво.

P.S.
Еще могу посоветовать сгенерировать документацию по QtCreator Doxygen-ом. Очень помогает. :)

Автор: Litkevich Yuriy 9.11.2009, 4:17

heiheshang, что-то я в Git-хранилище этого DuiEditor не вижу. Может прибили уже?

Автор: Гость_heiheshang_* 9.11.2009, 7:46

Цитата(frg10 @ 8.11.2009, 23:11) *
Цитата(Гость_Гость_heiheshang_*_* @ 8.11.2009, 19:11) *
Может сам класс мне и не нужен, главное получить его функционал,если подскажите как им воспользоваться буду благодарен.


Я могу вам посоветовать подробнее разобраться с архитектурой QtCreator. Мне очень помог документ http://www.vcreatelogic.com/downloads/files/Writing-Qt-Creator-Plugins.pdf. Как понятно из названия, там описывается как писать собственные плагины, ну и параллельно разбирается архитектура. А дальше нужно просто брать исходники самого креатора и разбираться. :D Кстати, всем советую, потому что сделано все очень красиво.

P.S.
Еще могу посоветовать сгенерировать документацию по QtCreator Doxygen-ом. Очень помогает. :)

Просмотр ничего не дал, так и осталось неясным как методы вызывать плагина.

Автор: frg10 9.11.2009, 21:45

Disclaimer: пишу все чисто теоретически - на практике ничего из нижеперечисленного не делал.

Если вы действительно хотите взяться за это, то приготовьтесь потянуть себе много всего из QtCreator. Вот мне кажется минимум:
1) ExtensionSystem - загрузка и управление плагинами
2) Aggregation - аггрегация объектов
3) CorePlugin - собственно ядро QtCreator. Требуется для работы любого плагина.
4) TextEditor - требуется для DuiEditor
5) Find, QuickOpen - требуются для TextEditor
6) Сам DuiEditor

Далее приготовьтесь:
1) Необходимо загрузить и инициализировать все плагины. Этим занимается PluginManager из ExtensionSystem. Как это делается можно посмотреть в qtcreator/app/main.cpp.
2) Core при загрузке создает главное окно приложения. Т.е. создастся окно QtCreator с меню и панельками.
3) Когда плагин инициализируется, он регистрирует все объекты, которые предоставляет, в PluginManager. Соответственно, если вы хотите использовать этот функционал, то вам нужно получать эти объекты из PluginManager-а или можно воспользоваться интерфейсом ICore. Второй вариант гораздо проще.
Конкретно DuiEditor экспортирует:
- фабрику классов для создания редакторов.
- визард для создания QML файлов
- объект Code Completion
- подсветку редактора

Для примера, допустим что вам нужно открыть редактор QML. Класс ICore предоставляет доступ к различным менеджерам. В том числе, там есть EditorManager. Этот менеджер управляет редакторами и может их создавать (внутри у него есть список всех зарегистрированных фабрик). Создать редактор можно так:

IEditor* editor = ICore::instance()->editorManager()->openEditor(fileName, "application/x-dui");

mimetype передавать не обязательно, если файл имеет расширение qml.
Получаем указатель на интерфейс IEditor - это и есть редактор. Через функцию IEditor::widget() получаем окно и делаем с ним все что угодно.

Надеюсь помог. :)
Если хотите дальше разрабатывать эту тему, то без ковыряния исходников никак не обойтись.

Автор: Гость_heiheshang_* 10.11.2009, 10:19

frg10
Копание в коде привело меня к такому результату

QString titlePattern = tr("Memory $");

        EditorManager* manager = EditorManager::instance();
        IEditor* editor = manager->openEditorWithContents(Core::Constants::K_DEFAULT_TEXT_EDITOR, &titlePattern);

но такой код генерит исключение. Может подскажете где копать , загрузить библиотеки или еще чего установить для приложения?

Автор: frg10 10.11.2009, 12:38

А что, то что я написал не работает? Вы все плагины загрузили?

Автор: Гость_heiheshang_* 10.11.2009, 15:26

Цитата(frg10 @ 10.11.2009, 12:38) *
А что, то что я написал не работает? Вы все плагины загрузили?

Не работает
ASSERTION style FAILED AT manhattanstyle.cpp:101

Делал так , скопировал из main.cpp
ExtensionSystem::PluginManager pluginManager;
    pluginManager.setFileExtension(QLatin1String("pluginspec"));

    QStringList pluginPaths;
    pluginPaths << qApp->applicationDirPath()+"/plugins";
    pluginManager.setPluginPaths(pluginPaths);


    const PluginSpecSet plugins = pluginManager.plugins();
    ExtensionSystem::PluginSpec *coreplugin = 0;
    foreach (ExtensionSystem::PluginSpec *spec, plugins) {
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1String(",")));
        const QString reason = QCoreApplication::translate("Application", "Couldn't find 'Core.pluginspec' in %1").arg(nativePaths);
        qDebug() << reason;
    //    return 1;
    }
    if (coreplugin->hasError()) {
        qDebug() << coreplugin->errorString();
    //    return 1;
    }

    pluginManager.loadPlugins();
    if (coreplugin->hasError()) {
        qDebug() << coreplugin->errorString();
    //    return 1;
    }

        QString titlePattern = tr("Memory $");
        ICore *core = ICore::instance();
        EditorManager* manager = EditorManager::instance();
        IEditor* editor = manager->openEditorWithContents(Core::Constants::K_DEFAULT_TEXT_EDITOR, &titlePattern);


Автор: frg10 10.11.2009, 17:34

Гм... У меня ваш код без последних четрех строк отлично работает с QtCreator 1.2.1. На какой строчке у вас падает?

Автор: Гость_heiheshang_* 10.11.2009, 17:42

Цитата(frg10 @ 10.11.2009, 17:34) *
Гм... У меня ваш код без последних четрех строк отлично работает с QtCreator 1.2.1. На какой строчке у вас падает?

Вот на этой выпадает, чет со стилем не так раз на него ругается.
pluginManager.loadPlugins();


Автор: frg10 10.11.2009, 18:01

Да, не получается у него стиль загрузить. Просто QtCreator запускается? Под какой системой сидите?
Попробуйте вставит вначале программы, после создания QApplication строчку:

qDebug() << qApp->style()->objectName();

Что выдаст?

Автор: Гость_heiheshang_* 10.11.2009, 18:23

Цитата(frg10 @ 10.11.2009, 18:01) *
Да, не получается у него стиль загрузить. Просто QtCreator запускается? Под какой системой сидите?
Попробуйте вставит вначале программы, после создания QApplication строчку:
qDebug() << qApp->style()->objectName();

Что выдаст?

Ни че не выдает хотя стоит QApplication::setStyle(new QWindowsStyle);

Автор: frg10 10.11.2009, 23:15

Цитата(Гость_Гость_heiheshang_*_* @ 10.11.2009, 18:23) *
Ни че не выдает хотя стоит QApplication::setStyle(new QWindowsStyle);

Тогда нужно или вообще убрать принудительную установку стиля, или сделать вот так:
QWindowsStyle* windowsStyle = new QWindowsStyle;
windowsStyle->setObjectName("windows");
QApplication::setStyle(windowsStyle)

Автор: Litkevich Yuriy 11.11.2009, 3:47

Стиль лучше устанавливать через фабрику:

QStyle *pStyle = QStyleFactory::create("windows");//Cleanlooks Plastique windowsxp
if (pStyle){
    QApplication::setStyle(pStyle);
    qApp->setPalette(pStyle->standardPalette());
}
и проверять указатель, т.к. стиля может не существовать на данной конкретной машине

Автор: frg10 11.11.2009, 5:05

Litkevich Yuriy
Да, так действительно лучше. Фабрика сама вызовет setObjectName для объекта стиля.

Автор: Гость_heiheshang_* 11.11.2009, 17:29

Цитата(frg10 @ 10.11.2009, 23:15) *
Цитата(Гость_Гость_heiheshang_*_* @ 10.11.2009, 18:23) *
Ни че не выдает хотя стоит QApplication::setStyle(new QWindowsStyle);

Тогда нужно или вообще убрать принудительную установку стиля, или сделать вот так:
QWindowsStyle* windowsStyle = new QWindowsStyle;
windowsStyle->setObjectName("windows");
QApplication::setStyle(windowsStyle)


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

Автор: frg10 11.11.2009, 18:35

Цитата(Гость_Гость_heiheshang_*_* @ 11.11.2009, 17:29) *
Получилось загрузить плагины, но при их загрузке вылетает окно qtcreator, а на кой оно мне

А я предупреждал :)
Цитата(Гость_Гость_heiheshang_*_* @ 11.11.2009, 17:29) *
и редактор не показывается, хотя создается.

Ну дальше ничем помочь не могу. Хотя интересно будет узнать о результатах.

P.S. Может он невидимым создается?

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)