2

LinuxでGCCを使用してQt4.8.3を使用しています。QtPluginを使用してモジュラーアプリケーションを作成しようとしています。アプリケーションはいくつかの基本機能を記述し、プラグインのホストがすべての固有の機能を提供します。各プラグインはファクトリを使用してクラスの複数のインスタンスを提供し、ファクトリクラスと提供されるクラスで構成されます。

現在、アプリケーションはコンパイル中ですが、実行されておらず、などのエラーが発生していCannot load library ~: (~: undefined symbol: _ZTI8Base16staticMetaObjectE)ます。このエラーを修正する方法がわかりません。Baseのすべての言及を削除すると問題は修正されますが、インスタンスはそのクラスから派生する必要があるため、それが機能するとは思いません。

以下のプロジェクトの構造を実行可能ファイルと単一のプラグインに含めました(これらはすべて現在同一であり、同じ問題があります)。

お手伝いいただきありがとうございます。

ディレクトリ構造

main_project
+- main_project.pro
+- app/
| +- app.pro
| +- main.cpp
| +- factoryinterface.h
| +- base.h
| +- base.cpp
|
+- counter/
  +- counter.pro
  +- counter.h
  +- counterfactory.cpp
  +- counterfactory.h
  +- counter.cpp

main_project.pro

TEMPLATE = subdirs

SUBDIRS += \
    app \
    counter

app.pro

QT       += core

QT       -= gui

DESTDIR = ../
TARGET = app_exec
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app

SOURCES += main.cpp \
    base.cpp

HEADERS += \
    base.h \
    factoryinterface.h

factoryinterface.h

#ifndef FACTORYINTERFACE_H
#define FACTORYINTERFACE_H

#include <QtPlugin>
#include "base.h"

class FactoryInterface {
public:
    virtual ~FactoryInterface() {}
    virtual Base *get() = 0;
    virtual QString name() = 0;
};

Q_DECLARE_INTERFACE(FactoryInterface,
                    "com.example.FactoryInterface/1.0")

#endif // FACTORYINTERFACE_H

base.h

#ifndef BASE_H
#define BASE_H

#include <QObject>

#include <QString>
#include <QStringList>
#include <QHash>

class Base : public QObject {
    Q_OBJECT
public:
    Base(QObject *parent = 0);
    virtual ~Base();

    virtual QString name();

signals:

public slots:

protected:
    QString name_;
};

#endif // BASE_H

base.cpp

#include "base.h"

Base::Base(QObject *parent) :
    QObject(parent)
{
}

Base::~Base()
{
}

QString Base::name()
{
    return name_;
}

main.cpp

#include <QtCore/QCoreApplication>

#include <QDir>
#include <QPluginLoader>
#include <QDebug>
#include "factoryinterface.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QDir pluginDir(a.applicationDirPath());
    pluginDir.cd("plugins");
    foreach(QString filename, pluginDir.entryList(QDir::Files))
    {
        QPluginLoader loader(pluginDir.absoluteFilePath(filename));
        QObject *plugin = loader.instance();

        if (plugin)
        {
            FactoryInterface *i = qobject_cast<FactoryInterface*>(plugin);

            if (i)
            {
                qDebug() << " :" << i->name();
            }
        } else {
            qDebug() << loader.errorString();
        }
    }

    return a.exec();
}

counter.pro

QT       -= gui
CONFIG   += plugin

TARGET = $$qtLibraryTarget(counter)
TEMPLATE = lib

DEFINES += COUNTER_LIBRARY

SOURCES += counter.cpp \
    counterfactory.cpp

HEADERS += counter.h \
    counterfactory.h

INCLUDEPATH += ../app

DESTDIR = ../plugins

symbian {
    MMP_RULES += EXPORTUNFROZEN
    TARGET.UID3 = 0xE5B38B75
    TARGET.CAPABILITY = 
    TARGET.EPOCALLOWDLLDATA = 1
    addFiles.sources = counter.dll
    addFiles.path = !:/sys/bin
    DEPLOYMENT += addFiles
}

unix:!symbian {
    maemo5 {
        target.path = /opt/usr/lib
    } else {
        target.path = /usr/lib
    }
    INSTALLS += target
}

counter.h

#ifndef COUNTER_H
#define COUNTER_H

#include <QObject>
#include "base.h"

class Counter : public Base {
    Q_OBJECT
public:
    Counter();
};

#endif // COUNTER_H

counter.cpp

#include "counter.h"


Counter::Counter()
{
    name_ = "Counter";
}

counterfactory.h

#ifndef COUNTER_H
#define COUNTER_H

#include <QObject>
#include "factoryinterface.h"
#include "base.h"
#include "counter.h"

class CounterFactory : public QObject, public FactoryInterface
{
    Q_OBJECT
    Q_INTERFACES(FactoryInterface)
public:
    explicit CounterFactory(QObject *parent = 0);
    Base *get();
    QString name();

signals:

public slots:

};

#endif // COUNTER_H

counterfactory.cpp

#include "counterfactory.h"


CounterFactory::CounterFactory(QObject *parent) :
    QObject(parent)
{
}

Base *CounterFactory::get()
{
    return new Counter;
}

QString CounterFactory::name()
{
    return "Counter";
}

Q_EXPORT_PLUGIN2(counter, CounterFactory)

編集:デバッグモードでコンパイルした後のエラーメッセージを更新しました。

編集: BaseNodeクラスをエクスポート/インポートしようとしましたが、これも機能しませんでした。それが完全に間違っているのか、それとも間違っているのかわかりません。Baseクラスに次の変更が加えられました(BASE_LIBRARYがapp.proファイルのDEFINESに追加されました)。

#include <QtCore/qglobal.h>

#if defined(BASE_LIBRARY)
#  define BASESHARED_EXPORT Q_DECL_EXPORT
#else
#  define BASESHARED_EXPORT Q_DECL_IMPORT
#endif

class BASESHARED_EXPORT Base : public QObject {
4

1 に答える 1

0

解決策は、baseクラスをcounter.proファイルに追加することであることが判明しました。完全に更新されたcounter.proファイルを以下にリストしましたが、唯一の変更はHEADERSとSOURCESへの追加でした。

counter.pro

QT       -= gui
CONFIG   += plugin

TARGET = $$qtLibraryTarget(counter)
TEMPLATE = lib

DEFINES += COUNTER_LIBRARY

SOURCES += counter.cpp \
    counterfactory.cpp \
    ../app/base.cpp

HEADERS += counter.h \
    counterfactory.h \
    ../app/base.h

INCLUDEPATH += ../app

DESTDIR = ../plugins

symbian {
    MMP_RULES += EXPORTUNFROZEN
    TARGET.UID3 = 0xE5B38B75
    TARGET.CAPABILITY = 
    TARGET.EPOCALLOWDLLDATA = 1
    addFiles.sources = counter.dll
    addFiles.path = !:/sys/bin
    DEPLOYMENT += addFiles
}

unix:!symbian {
    maemo5 {
        target.path = /opt/usr/lib
    } else {
        target.path = /usr/lib
    }
    INSTALLS += target
}
于 2013-01-09T15:21:49.003 に答える