Qt World Summit: Register Today!

COM object and QtVariant casting issue

  • Hello every one,
    I'm trying to use a COM object and I'm having trouble casting a returned function value. I am using Qt 5.7.0 and I got .h and .cpp file for COM object with dumpcpp tool.

    class SCAPILIB_EXPORT IAttrList : public QAxObject
        IAttrList(IDispatch *subobject = 0, QAxObject *parent = 0)
        : QAxObject((IUnknown*)subobject, parent)
        Method AddItem
        method AddItem
        inline void AddItem(Attr Attribute, const QVariant& value);
        Method FindItemIndex
        method FindItemIndex
        inline int FindItemIndex(int startIndex, SCAPILib::Attr Attribute);
        Method GetCount
        method GetCount
        inline int GetCount();
        Method GetIndex
        method GetIndex
        inline QVariant GetIndex(int index, Attr& pAttribute);
        Method GetItem
        method GetItem
        inline QVariant GetItem(Attr Attribute);
        Method OutputToString
        method OutputToString
        inline QString OutputToString();
        Method RestoreFromBlob
        method RestoreFromBlob
        inline void RestoreFromBlob(QVariant blob);
        Method SaveToBlob
        method SaveToBlob
        inline void SaveToBlob(QVariant& pBlob);
        Method SetIndex
        method SetIndex
        inline void SetIndex(int index, SCAPILib::Attr Attribute, const QVariant& value);
    // meta object functions
        static const QMetaObject staticMetaObject;
        virtual const QMetaObject *metaObject() const { return &staticMetaObject; }
        virtual void *qt_metacast(const char *);

    The function GetItem always returned a QVariant, usually the QVariant contain a QString, QInt or QBool, but with a determinate attribute the returned value will be a pointer to the base class(IAttrList *).

    inline QVariant IAttrList::GetItem(Attr Attribute)
        QVariant qax_result;
        void *_a[] = {(void*)&qax_result, (void*)&Attribute};
        qt_metacall(QMetaObject::InvokeMetaMethod, 12, _a);
        return qax_result;

    I can use the function of the COM object just fine, except when it will be return a indicated class pointer. In this case de QVariant returnet type is (IUnknown *) and I not able to cast this to (IAttrLits *).

    I'm tried with:

    IAttrList * Attr = AttrList.GetItem(Some_Attribute).Value<IAttrList *>();

    But compiler returned error: static assertion failed: qobject_cast requires the type to have a Q_OBJECT macro

    Which I understand is normal because, according to QT documentation, classes derived from QAxObject can not contain the Q_OBJECT macro.

    I have also tried with:

    IAttrList * attr = static_cast<IAttrList *>(AttrList.GetItem(Some_attribute).data());


    IAttrList * attr = static_cast<IAttrList *>(AttrList.GetItem(Some_attribute).value<void *>();

    It's compile but the AttrList pointer does not seem to be valid because I get a segmentation fault to try use it.

    I do not know what the problem might be, any subgestion?. Thanks in advanced.

  • Hi @mlago,

    Two things to note here.

    1. You have to add Q_OBJECT macro in private section of the class.
    2. Before doing qvariant_cast, non-standard data types need to be registered, using the qRegisterMetaType() function

  • Hi @sonulohani ,
    Thanks for the answer. The class was generated by dumpcpp from a COM object dll and I can't add Q_OBJECT macro because the class derive of QAxObject and not from QObject.

  • Moderators

    @mlago said in COM object and QtVariant casting issue:

    the class derive of QAxObject and not from QObject.

    QAxObject derives from QObject however. If I remember correctly, you can dynamic cast the unknown interface too. Something along the lines of:

    IUnknown * interface; //< Comes from the COM API
    IAttrList * attrList = dynamic_cast<IAttrList *>(interface);
    if (attrList)  {
        // ... Do things
    else  {
        // Not dealing with that type of object at all ...

  • Hi,
    I tried with you say but not work:

    error: cannot dynamic_cast 'interface' (of type 'struct IUnknown*') to type 'class IAttrList*' (source is a pointer to incomplete type)

    I thinking that de right way is using QueryInterface but I have not been able to make it work yet. First all i dont have the UUID class because the dumpcpp dont generate any for this class. I tried asigned one with SetControl method, but in this case, the call:

    HRESULT Hr = AttrList.QueryIntrface (IID_AttrList, (void **) & var);

    Always returns, 0x80004001 E_NOTIMPL

    I do not understand how something seemingly simple may be getting so complicated.

    Thanks once again.

  • Hi, to get an instance of IAttrList, I think you need to create it first. (COM doesn't do that for you). Perhaps instead of calling QueryInterface, try a querySubObject(), something like:

    QAxObject *iAttrList = AttrList.GetItem(Some_Attribute).querySubObject("IAttrList");

  • Thanks @hskoglund ,
    The QVariant object returned by the function GetItem not have a QuerySubObject method and I can`t do the call in this way.

    A casting from the QVariant to QAxObject is posible:

     QAxObject * axObj =AttrList.GetItem(some_attribute).value<QAxObject *>();

    but return with a null pointer in axObj.

    thank you anyway.

  • Hmm, if you have some .NET code that successfully retrieves an IAttrList class instance, could you post it here..

  • In case it helps, I bring another part of the code, of the class header file showing in my first post, where it refers to MetaTypeFuntionHelper, I have not found documentation about this struct:

    struct QMetaTypeFunctionHelper<SCAPILib::IAttrList, /* Accepted */ true> {
        static void Destruct(void *t)
        static void *Construct(void *where, const void *t)
            return new (where) SCAPILib::IAttrList;
    #ifndef QT_NO_DATASTREAM
        static void Save(QDataStream &stream, const void *t) { stream << *static_cast<const SCAPILib::IAttrList*>(t); }
        static void Load(QDataStream &stream, void *t) { stream >> *static_cast<SCAPILib::IAttrList*>(t); }
    #endif // QT_NO_DATASTREAM

    Today I have also tried adding Q_DECLARE_METATYPE() macro to the end of the class declaration, outside the namespace:

    namespace SCAPILib {

    But with these compiler errors:

    qmetatype.h:1864: error: specialization of 'QMetaTypeId<SCAPILib::IAttrList>' after instantiation
         struct QMetaTypeId< TYPE >	 
    qmetatype.h:1864: error: redefinition of 'struct QMetaTypeId<SCAPILib::IAttrList>'
         struct QMetaTypeId< TYPE >
    qmetatype.h:1596: error: previous definition of 'struct QMetaTypeId<SCAPILib::IAttrList>'
     struct QMetaTypeId : public QMetaTypeIdQObject<T>

Log in to reply