Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. COM object and QtVariant casting issue
Qt 6.11 is out! See what's new in the release blog

COM object and QtVariant casting issue

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 4 Posters 4.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mlago
    wrote on last edited by mlago
    #1

    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
    {
    public:
        IAttrList(IDispatch *subobject = 0, QAxObject *parent = 0)
        : QAxObject((IUnknown*)subobject, parent)
        {
            internalRelease();
        }
    
        /*
        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());
    

    and

    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.

    S 1 Reply Last reply
    0
    • M mlago

      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
      {
      public:
          IAttrList(IDispatch *subobject = 0, QAxObject *parent = 0)
          : QAxObject((IUnknown*)subobject, parent)
          {
              internalRelease();
          }
      
          /*
          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());
      

      and

      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.

      S Offline
      S Offline
      sonulohani
      wrote on last edited by
      #2

      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
      1 Reply Last reply
      0
      • M Offline
        M Offline
        mlago
        wrote on last edited by mlago
        #3

        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.

        kshegunovK 1 Reply Last reply
        0
        • M mlago

          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.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @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 ...
          }
          

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mlago
            wrote on last edited by mlago
            #5

            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.

            1 Reply Last reply
            0
            • hskoglundH Offline
              hskoglundH Offline
              hskoglund
              wrote on last edited by
              #6

              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");
              
              1 Reply Last reply
              0
              • M Offline
                M Offline
                mlago
                wrote on last edited by
                #7

                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.

                1 Reply Last reply
                0
                • hskoglundH Offline
                  hskoglundH Offline
                  hskoglund
                  wrote on last edited by
                  #8

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

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mlago
                    wrote on last edited by mlago
                    #9

                    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:

                    template<>
                    struct QMetaTypeFunctionHelper<SCAPILib::IAttrList, /* Accepted */ true> {
                        static void Destruct(void *t)
                        {
                            Q_UNUSED(t)
                            static_cast<SCAPILib::IAttrList*>(t)->SCAPILib::IAttrList::~IAttrList();
                        }
                        static void *Construct(void *where, const void *t)
                        {
                            Q_ASSERT(!t);
                            Q_UNUSED(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 {
                    (...)
                    #endif
                    }
                    Q_DECLARE_METATYPE(SCAPILib::IAttrList)
                    

                    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>
                    
                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved