【问题标题】:How to iteratively qobject_cast items from a QList如何从 QList 迭代地 qobject_cast 项目
【发布时间】:2020-07-27 18:43:12
【问题描述】:

我正在尝试 qt 示例中的“echo 插件”,我更改了一些东西来尝试并偶然发现了一个我无法修复的错误。 这是原始的 Echo Window 类

#include <QWidget>
#include "echointerface.h"
QT_BEGIN_NAMESPACE
class QString;
class QLineEdit;
class QLabel;
class QPushButton;
class QGridLayout;
QT_END_NAMESPACE

//! [0]
class EchoWindow : public QWidget
{
    Q_OBJECT

public:
    EchoWindow();

private slots:
    void sendEcho();

private:
    void createGUI();
    bool loadPlugin();

    EchoInterface *echoInterface;  ***********
    QLineEdit *lineEdit;
    QLabel *label;
    QPushButton *button;
    QGridLayout *layout;

};

我改变的是我用星星突出显示的行。我把它改成这样的Qlist

QList<EchoInterface *>echoInterfaces 

还改变了函数 LoadPlugin() 的实现 从此:-

bool EchoWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            echoInterface = qobject_cast<EchoInterface *>(plugin);
            if (echoInterface)
                return true;
        }
    }

    return false;
}

对此:-

    bool ModifyWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            foreach ( EchoInterface *a, echoInterfaces)
            {
               a = qobject_cast <EchoInterface *>(plugin);
            }
                if(!echoInterfaces.contains(NULL))
                    return true;
            }

        }
    return false;
}

提前致谢

【问题讨论】:

  • 问题是什么?如果您有编译器或链接器错误,请在您的问题中包含消息verbatim。谢谢。
  • @PaulSanders 你好,问题是我不能确定 foreach 循环是否正常工作。如果您对如何 qobject_cast 列出项目有经验,您可以查看我所做的并告诉我哪里做错了。及其运行时错误。它只是说插件无法加载。这不是链接器错误
  • 抱歉,我没有这种经验,但在这种情况下,通常的做法是在调试器中逐步执行代码(推荐)或在代码中插入打印语句以查看内容正在发生(“穴居人调试”)。

标签: c++ qt c++11 plugins


【解决方案1】:

如果我的猜测是正确的,您想存储一组接口,而您的问题是如何正确读取它。 我明白了

假设是所有错误的根源

:) 但是我们不要关注这样做的原因,而只是猜测(再次)EchoInterface 是各种可用接口的基类。

你的代码有什么问题:

bool ModifyWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            foreach ( EchoInterface *a, echoInterfaces)
            {
               // this is pointless - only a tmp variable 'a' is modified for a while
               // just to be reset on the next iteration
               a = qobject_cast <EchoInterface *>(plugin);
            }
                if(!echoInterfaces.contains(NULL)) // use nullptr instead of NULL 
                    return true; // echoInterfaces is always empty, so it doesnt contain null
            }

        }
    return false;
}

您正在寻找的变化:

bool EchoWindow::loadPlugin()
{
    QDir pluginsDir(QCoreApplication::applicationDirPath());
    pluginsDir.cd("plugins");
    const QStringList entries = pluginsDir.entryList(QDir::Files);
    for (const QString &fileName : entries) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        // it's unnecessary to check if plugin == nullptr,
        // because in this case qobject_cast returns nullptr
        // and we go directly to pluginLoader.unload();
        if (EchoInterface * echoIface = qobject_cast<EchoInterface *>(plugin)) {
            echoInterfaces.append(echoIface); // populate the collection with a valid pointer
            continue; // to avoid the pluginLoader.unload() call which would destroy the echoIface
        }
        pluginLoader.unload();
    }

    // Since we ensured that the echoInterfaces can contain only valid pointers,
    // no additional checks are necessary — the fact that something is stored in the collection is enough
    return !echoInterfaces.isEmpty();

    // or
    // return echoInterfaces.size() > 0;
    // or even just
    // return echoInterfaces.size();
}

如果我的假设是错误的,那么我们肯定需要一个更详细的问题。

【讨论】:

    猜你喜欢
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    • 2018-10-12
    • 2016-04-25
    • 1970-01-01
    相关资源
    最近更新 更多