首页 > 其他分享 >bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericRe

bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericRe

时间:2024-10-27 11:58:23浏览次数:6  
标签:const idx int QGenericArgument member inline return val0 priv



class QMetaMethodPrivate : public QMetaMethodInvoker
{
public:
    static const QMetaMethodPrivate *get(const QMetaMethod *q)
    { return static_cast<const QMetaMethodPrivate *>(q); }

    inline QByteArray signature() const;
    inline QByteArray name() const;
    inline int typesDataIndex() const;
    inline const char *rawReturnTypeName() const;
    inline int returnType() const;
    inline int parameterCount() const;
    inline int parametersDataIndex() const;
    inline uint parameterTypeInfo(int index) const;
    inline int parameterType(int index) const;
    inline void getParameterTypes(int *types) const;
    inline const QtPrivate::QMetaTypeInterface *returnMetaTypeInterface() const;
    inline const QtPrivate::QMetaTypeInterface *const *parameterMetaTypeInterfaces() const;
    inline QByteArray parameterTypeName(int index) const;
    inline QList<QByteArray> parameterTypes() const;
    inline QList<QByteArray> parameterNames() const;
    inline QByteArray tag() const;
    inline int ownMethodIndex() const;
    inline int ownConstructorMethodIndex() const;

private:
    void checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface, int index) const;
    QMetaMethodPrivate();
};
} // unnamed namespace

auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
                                    Qt::ConnectionType connectionType,
                                    qsizetype paramCount, const void *const *parameters,
                                    const char *const *typeNames,
                                    const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
{
    auto object = static_cast<QObject *>(target);
    auto priv = QMetaMethodPrivate::get(&self);
    constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
    auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
    auto param = const_cast<void **>(parameters);

    Q_ASSERT(priv->mobj);
    Q_ASSERT(self.methodType() == Constructor || object);
    Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
             priv->mobj->cast(object));
    Q_ASSERT(paramCount >= 1);  // includes the return type
    Q_ASSERT(parameters);
    Q_ASSERT(typeNames);
    Q_ASSERT(MetaTypesAreOptional || metaTypes);

    if ((paramCount - 1) < qsizetype(priv->data.argc()))
        return InvokeFailReason::TooFewArguments;

    // 0 is the return type, 1 is the first formal parameter
    auto checkTypesAreCompatible = [=](int idx) {
        uint typeInfo = priv->parameterTypeInfo(idx - 1);
        QLatin1StringView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);

        if ((typeInfo & IsUnresolvedType) == 0) {
            // this is a built-in type
            if (MetaTypesAreOptional && !metaTypes)
                return int(typeInfo) == QMetaType::fromName(userTypeName).id();
            return int(typeInfo) == metaTypes[idx]->typeId;
        }

        QLatin1StringView methodTypeName = stringDataView(priv->mobj, typeInfo & TypeNameIndexMask);
        if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
            // compatibility call, compare strings
            if (methodTypeName == userTypeName)
                return true;

            // maybe the user type needs normalization
            QByteArray normalized = normalizeTypeInternal(userTypeName.begin(), userTypeName.end());
            return methodTypeName == QLatin1StringView(normalized);
        }

        QMetaType userType(metaTypes[idx]);
        Q_ASSERT(userType.isValid());
        if (QMetaType(methodMetaTypes[idx - 1]) == userType)
            return true;

        // if the parameter type was NOT only forward-declared, it MUST have
        // matched
        if (methodMetaTypes[idx - 1])
            return false;

        // resolve from the name moc stored for us
        QMetaType resolved = QMetaType::fromName(methodTypeName);
        return resolved == userType;
    };

    // force all types to be registered, just in case
    for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
        QMetaType(metaTypes[i]).registerType();

    // check formal parameters first (overload set)
    for (qsizetype i = 1; i < paramCount; ++i) {
        if (!checkTypesAreCompatible(i))
            return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
    }

    // handle constructors first
    if (self.methodType() == Constructor) {
        if (object) {
            qWarning("QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
                     self.methodSignature().constData(), object);
            return InvokeFailReason::ConstructorCallOnObject;
        }

        if (!parameters[0]) {
            qWarning("QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
                     self.methodSignature().constData());
            return InvokeFailReason::ConstructorCallWithoutResult;
        }

        if (!MetaTypesAreOptional || metaTypes) {
            if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
                qWarning("QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
                         metaTypes[0]->name, self.methodSignature().constData());
                return InvokeFailReason::ReturnTypeMismatch;
            }
        }

        int idx = priv->ownConstructorMethodIndex();
        if (priv->mobj->static_metacall(QMetaObject::CreateInstance, idx, param) >= 0)
            return InvokeFailReason::ConstructorCallFailed;
        return {};
    }

    // regular type - check return type
    if (parameters[0]) {
        if (!checkTypesAreCompatible(0)) {
            const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
            qWarning("QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
                     " cannot convert from %s to %s during invocation",
                     priv->mobj->className(), priv->methodSignature().constData(),
                     priv->rawReturnTypeName(), retType);
            return InvokeFailReason::ReturnTypeMismatch;
        }
    }

    Qt::HANDLE currentThreadId = nullptr;
    QThread *objectThread = nullptr;
    auto receiverInSameThread = [&]() {
        if (!currentThreadId) {
            currentThreadId = QThread::currentThreadId();
            objectThread = object->thread();
        }
        if (objectThread)
            return currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
        return false;
    };

    // check connection type
    if (connectionType == Qt::AutoConnection)
        connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
    else if (connectionType == Qt::ConnectionType(-1))
        connectionType = Qt::DirectConnection;

#if !QT_CONFIG(thread)
    if (connectionType == Qt::BlockingQueuedConnection) {
        connectionType = Qt::DirectConnection;
    }
#endif

    // invoke!
    int idx_relative = priv->ownMethodIndex();
    int idx_offset = priv->mobj->methodOffset();
    QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;

    if (connectionType == Qt::DirectConnection) {
        if (callFunction)
            callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
        else if (QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) >= 0)
            return InvokeFailReason::CallViaVirtualFailed;
    } else if (connectionType == Qt::QueuedConnection) {
        if (parameters[0]) {
            qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
                     "queued connections");
            return InvokeFailReason::CouldNotQueueParameter;
        }

        auto event = std::make_unique<QMetaCallEvent>(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount);
        QMetaType *types = event->types();
        void **args = event->args();

        // fill in the meta types first
        for (int i = 1; i < paramCount; ++i) {
            types[i] = QMetaType(methodMetaTypes[i - 1]);
            if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
                types[i] = QMetaType(metaTypes[i]);
            if (!types[i].iface())
                types[i] = priv->parameterMetaType(i - 1);
            if (!types[i].iface() && typeNames[i])
                types[i] = QMetaType::fromName(typeNames[i]);
            if (!types[i].iface()) {
                qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
                         typeNames[i]);
                return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
            }
        }

        // now create copies of our parameters using those meta types
        for (int i = 1; i < paramCount; ++i)
            args[i] = types[i].create(parameters[i]);

        QCoreApplication::postEvent(object, event.release());
    } else { // blocking queued connection
#if QT_CONFIG(thread)
        if (receiverInSameThread()) {
            qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
                     "Receiver is %s(%p)", priv->mobj->className(), object);
            return InvokeFailReason::DeadLockDetected;
        }

        QSemaphore semaphore;
        QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
                                                        nullptr, -1, param, &semaphore));
        semaphore.acquire();
#endif // QT_CONFIG(thread)
    }
    return {};
}




标签:const,idx,int,QGenericArgument,member,inline,return,val0,priv
From: https://www.cnblogs.com/DesertCactus/p/18508132

相关文章

  • Expression-bodied members (C# programming guide)
    Expressionbodydefinitionsletyouprovideamember'simplementationinaconcise,readableform.Youcanuseanexpressionbodydefinitionwheneverthelogicforanysupportedmember,suchasamethodorproperty,consistsofasingleexpression.A......
  • C++ Data Member Pointers 和 Member Function Pointers
    https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-pointers2.3MemberPointers2.3.1DataMemberPointersThebasicABIpropertiesofdatamemberpointertypesarethoseofptrdiff_t.Adatamemberpointerisrepresentedasthedatamember's......
  • TestMemberVar
    packagecom.shrimpking.t1;/***CreatedbyIntelliJIDEA.**@Author:Shrimpking*@create2024/9/1411:24*/publicclassTestMemberVar{staticintvar=1;publicstaticvoidmain(String[]args){System.out.println("......
  • Php:Call to a member function fetch_all() on bool in ... #0 {main} thrown in ...
    一、软件版本  软件版本:phpstudy_proV8.2.9;二、错误描述  在编写完连接数据库,执行相关的操作的代码之后,在浏览器运行时报如下错误:Fatalerror:UncaughtError:Calltoamemberfunctionfetch_all()onboolinD:\phpstudy_pro\WWW\test2.cc\contact.php:77St......
  • tz_member_prod
    CREATETABLE`tz_member_prod`( `prod_id`bigint(20)unsignedNOTNULLAUTO_INCREMENTCOMMENT'商品ID', `prod_name`varchar(255)DEFAULTNULLCOMMENT'商品名称', `prod_name_py`varchar(255)DEFAULTNULLCOMMENT'商品名称拼音缩写', `ori......
  • Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.s
    环境:JDK21问题原因是Lombok,与JDK21兼容的最低Lombok版本是1.18.30,最小的SpringBoot版本是3.1.4。解决:将lombook版本改为1.18.30<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lomb......
  • VsCode C++ namespace has no member错误
    此问题VSCode C++插件本身bug解决办法一:还原c++插件到旧版本解决方法二:但此方法智能提示会有很多多余的信息(有缺陷)在官方未推出相应布丁之前,可按照以下步骤避免该问题:1、按顺序打开:文件》首选项》设置2、在右边,用户设置窗口添加以下代码:"C_Cpp.intelliSenseEngine":"TagP......
  • VS Code 提示 namespace “std“ has no member “***“ 解决方法
    问题:自己编写的代码没有问题,能够编译和运行,但是vscode一直向我显示错误信息,提示namespace"std"hasnomember"***"。解决方案:在 VSCode 打开c_cpp_properties.json文件,将cStandard和cppStandard改成统一标准:"cStandard":"c11","cppStandard":"c++11",......
  • Redis - Smembers性能优化
    命令概述SMembers命令用于获取一个集合的所有成员。它的语法如下:SMEMBERSkey其中,key是集合的名称。SMembers命令返回一个包含所有集合成员的数组。如果集合不存在,返回空数组。关键因素内存占用:Redis是内存数据库,因此集合的大小直接影响到内存使用量。网络传输:当使用S......
  • Fatal error: Call to a member function read() on a non-object in 错误解决方法(织
    大家都说这是因为织梦代码优化不好怎么着怎么着的,其实有一些是因为这个原因,但不是完全因为这个。dede登录后台卡死原因分析登录完后台,加载的分别为顶部、左侧、右侧内容三个部分。顶部只是简单的查询一下权限不会卡、左侧也是简单的查询了一下也不会卡,那么原因就是......