2016-04-25 10 views
2

Ich habe eine Qt-Anwendung, die benutzerdefinierte Plugins (geladen mit QPluginLoader) erlaubt, und diese Plugins können einige Schnittstellen implementieren und mit dem Q_INTERFACES() Makro deklarieren.Qt-Plugins: Gibt es eine Möglichkeit, alle Schnittstellen aufzulisten, die ein Plugin implementiert?

Wenn Sie Qt-Dokumentation unter unten stehenden Link aussehen, ich rede über den „low-level“ API: http://doc.qt.io/qt-5/plugins-howto.html

Nun, dies ist meine Frage: nachdem ich ein Plugin mit QPluginLoader lade, ist Gibt es eine Möglichkeit, alle Schnittstellen zu benennen, die es implementiert? Gibt es eine Möglichkeit zu nennen, was das Plugin im Q_INTERFACES() Makro von der Haupt-App, die das Plugin lädt, erklärt?

Die Anwendung funktioniert derzeit sowohl mit Qt4 als auch mit Qt5, aber eine Lösung, die nur mit Qt5 funktioniert, wäre ebenfalls akzeptabel.

+0

Qt erstellt definitiv Metadaten für die Schnittstellen, aber ich finde keine Möglichkeit, sie zu durchlaufen. – dtech

+0

@ddriver Die Metadaten werden sehr implizit erstellt: moc generiert Code, mit dem Sie das 'QObject' in eine Instanz der Schnittstelle umwandeln können, wenn Sie den Namen der Schnittstelle kennen. Die Daten werden nicht auf andere Weise gespeichert: Es gibt keine Liste von Schnittstellen irgendwo :( –

+0

Nun, es muss die tatsächlichen Strings für die Namen speichern, da das Meta-System mit String-Literalen arbeitet und Laufzeit-Lookups, es ist nur ein ernsthafte Unterlassung in der Gestaltung des Metasystems, dass diese Daten nicht auf eine nützlichere Weise strukturiert sind.Ich mag auch nicht die Tatsache, dass es für alles erzeugt wird, es wäre besser, wenn Sie angeben könnten, welche Art von Metadaten Sie wollen für ein bestimmtes Objekt – dtech

Antwort

1

Leider hat Qt nicht explizit die Liste der Schnittstellen hält :(

Das Beste, was Sie tun können, ist zu versuchen, die QObject * instance() vom Plugin Loader auf eine bestimmte Schnittstelle angegeben entweder mit einem Klassennamen zurück zu werfen oder .. mit seiner IID, qt_metacast verwenden, dh loader.instance()->qt_metacast("IFoo") Wenn das Ergebnis nicht Null ist, dann führt die gegebene Klasse die Schnittstelle

Alternativ können Sie jede Schnittstelle als Klassen Info hinzufügen, und Sie können sie dann aufzählen:

class Impl : public QObject { 
    Q_OBJECT 
    Q_INTERFACES(IFoo IBar) 
    Q_CLASSINFO("Interface", "IFoo") 
    Q_CLASSINFO("Interface", "IBar") 
} 

QStringList interfaces(QObject * obj) { 
    QStringList result; 
    auto count = obj->metaObject()->classInfoCount(); 
    for (int i = 0; i < count; ++i) { 
    auto info = obj->metaObject()->classInfo(i); 
    if (strcmp(info.name(), "Interface") == 0) 
     result << QString::fromLatin1(info.value()); 
    } 
    return result; 
} 

Wenn Sie sich auf diese Funktionalität verlassen möchten, sollten Sie Ihre Kopie von moc ändern, um automatisch relevante Klasseninformationen von Q_INTERFACES zu generieren. IIRC es ist nur ein paar Zeilen Wertänderung, ich habe sowas irgendwann einmal gemacht.

+0

Wenn Sie die Plugins implementieren, können Sie auch eine 'virtuelle QStringList interfaces()' in eine 'InterfaceInfo'-Schnittstelle einfügen und diese in jedes Plugin einfügen und manuell implementieren. – dtech

+0

@ddriver True :) –

+0

Danke für die Antwort! Es ist schade, dass Qt keine Möglichkeit bietet, Schnittstellen zu nummerieren. Für den Kontext war mein Ziel, eine Karte von allen verfügbaren Schnittstellen zu allen Plugins zu erstellen, die sie implementieren, sodass jeder, der mit einer bestimmten Schnittstelle interagieren möchte, alle verfügbaren Plugins abfragen kann. So konnte ich (unter anderem) ein Plugin-Abhängigkeitssystem implementieren. – Daniele

Verwandte Themen