Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

extract object * from QVariantList



  • hello

    I have a QVariantList property i one class that holds simple QObject derived objects (called Job)

     Q_PROPERTY(QVariantList selectedPrograms READ selectedPrograms NOTIFY selectedProgramsChanged)
    public:
      QVariantList selectedPrograms(){
            QVariantList progList;
            for(auto prg : m_selectedPrograms){
                progList.append(QVariant::fromValue(prg));
            }
            return progList;
        }
    private:
     QList<Job*> m_selectedPrograms;
    
    

    is there a way to reconstruct a Job object from my QVariantList ?
    i try

    Job * j = (Job*)machine->selectedPrograms().at(0).value<void*>();
    
    Stack:
    #  1: ZN5QTest15toPrettyUnicodeEPKti() - 0x000000006edc27d0
    #  2: UnhandledExceptionFilter() - 0x00007ffb9d57f490
    #  3: memset() - 0x00007ffba0ec2fc0
    #  4: _C_specific_handler() - 0x00007ffba0eac640
    #  5: _chkstk() - 0x00007ffba0ec10e0
    #  6: RtlRaiseException() - 0x00007ffba0e89ef0
    #  7: KiUserExceptionDispatcher() - 0x00007ffba0ebfe40
    #  8: Unable to obtain symbol
    #  9: ZNK11QMetaMethod6invokeEP7QObjectN2Qt14ConnectionTypeE22QGenericReturnArgument16QGenericArgumentS5_S5_S5_S5_S5_S5_S5_S5_S5_() - 0x0000000068a82b70
    # 10: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7f90
    # 11: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7f90
    # 12: ZN5QTest5qInitEP7QObjectiPPc() - 0x000000006edc7f90
    # 13: ZN5QTest4qRunEv() - 0x000000006edcac70
    # 14: ZN5QTest5qExecEP7QObjectiPPc() - 0x000000006edcb060
    # 15: Unable to obtain symbol
    # 16: Unable to obtain symbol
    # 17: Unable to obtain symbol
    # 18: BaseThreadInitThunk() - 0x00007ffb9efb7bc0
    # 19: RtlUserThreadStart() - 0x00007ffba0e8ceb0
    

    do i have to implement a special constructor ?



  • @LeLev said in extract object * from QVariantList:

    is there a way to reconstruct a Job object from my QVariantList ?

    I will do it like this:

    Job * j = qobject_cast<Job *>(qvariant_cast<QObject *>(machine->selectedPrograms().first()));
    

  • Moderators

    @LeLev said in extract object * from QVariantList:

    i try

    Job * j = (Job*)machine->selectedPrograms().at(0).value<void*>();
    

    Your approach is correct, but why cast it to void *?

    Job * j = machine->selectedPrograms().at(0).value<Job *>();
    

    should do fine.

    Note I don't see any connection between the stack trace you posted and your reported problem. Are you sure they came from the same place? You may be barking up the wrong tree here ...



  • @KroMignon thank you very much !



  • hi @kshegunov thank you for your input

    @kshegunov said in extract object * from QVariantList:

    but why cast it to void *?

    my misstake sorry

    as you said

    Job * j = (Job*)machine->selectedPrograms().at(0).value<Job*>();
    

    worked fine also

    @kshegunov said in extract object * from QVariantList:

    Are you sure they came from the same place?

    well the code i show you comes from my unit tests (qt testlib), when it reaches my errornous line i have that output, that why i thought it was related, my bad

    void initTestCase(){
            qDebug()<<"Init...";
              machine = new MachineBackend();
              QVERIFY(&machine!=NULL);
        }
    
        void testConnectToHost(){
             machine->connectToServer("opc.tcp://127.0.0.1:4840",0);
            QTest::qWait(2000);
            QVERIFY(machine->connected());
        }
    
        void testAddProgram(){
            machine->addProgram("file.ext","C:/Users/Public/prog/AMG1/file.ext",0,0);
            QVERIFY(machine->selectedPrograms().count()==1);
            QVERIFY(machine->selectedPrograms().at(0)!=NULL);
        }
    
        void testAddedProgramValidity(){
    
         //   Job * j = (Job*)machine->selectedPrograms().at(0).value<void*>(); //  <<   it was crashing here so i 
         
         QVERIFY(j->nom() == "file.ext");
        //QVERIFY(j->xMax() > 1199 && j->xMax() < 1201);
        }
    

    thank you for the hints


  • Moderators

    @LeLev said in extract object * from QVariantList:

    well the code i show you comes from my unit tests

    Yep, I saw that. It also looks to me you're getting an exception raised, that's why I asked about the location. You should really call QVariant::canConvert<> before you actually do the conversion though.



  • @kshegunov if i try to call canConvert()

            int id = qMetaTypeId<Job>();
            if(machine->selectedPrograms().at(0).canConvert(id)){
                Job * j = (Job*)machine->selectedPrograms().at(0).value<Job*>();
                QVERIFY(j->nom() == "000TestGCODE.nc");
            }
    

    i get

    C:\Qt\5.13.0\mingw73_64\include\QtCore\qglobal.h:121: erreur : static assertion failed: Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system
     #  define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
                                                     ^
    

    so i added

    Q_DECLARE_METATYPE(Job)
    

    at the end of my Job class header.

    but i have lots of errors when i try to build

    C:\Qt\5.13.0\mingw73_64\include\QtCore\qmetatype.h:-1: In instantiation of 'static void* QtMetaTypePrivate::QMetaTypeFunctionHelper<T, Accepted>::Construct(void*, const void*) [with T = Job; bool Accepted = true]':
    C:\Qt\5.13.0\mingw73_64\include\QtCore\qmetatype.h:1748: required from 'int qRegisterNormalizedMetaType(const QByteArray&, T*, typename QtPrivate::MetaTypeDefinedHelper<T, (QMetaTypeId2<T>::Defined && (! QMetaTypeId2<T>::IsBuiltIn))>::DefinedType) [with T = Job; typename QtPrivate::MetaTypeDefinedHelper<T, (QMetaTypeId2<T>::Defined && (! QMetaTypeId2<T>::IsBuiltIn))>::DefinedType = QtPrivate::MetaTypeDefinedHelper<Job, true>::DefinedType]'
    C:\Qt\5.13.0\mingw73_64\include\QtCore\qmetatype.h:1748: required from 'int qRegisterNormalizedMetaType(const QByteArray&, T*, typename QtPrivate::MetaTypeDefinedHelper<T, (QMetaTypeId2<T>::Defined && (! QMetaTypeId2<T>::IsBuiltIn))>::DefinedType) [with T = Job; typename QtPrivate::MetaTypeDefinedHelper<T, (QMetaTypeId2<T>::Defined && (! QMetaTypeId2<T>::IsBuiltIn))>::DefinedType = QtPrivate::MetaTypeDefinedHelper<Job, true>::DefinedType]'
    C:\Qt\5.13.0\mingw73_64\include\QtCore\qmetatype.h:805: erreur : use of deleted function 'Job::Job(const Job&)'
                 return new (where) T(*static_cast<const T*>(t));
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    C:\Users\usr\Documents\project\src\job.h:20: 'Job::Job(const Job&)' is implicitly deleted because the default definition would be ill-formed:
     class Job : public QObject
           ^~~
    
    

  • Moderators

    @LeLev said in extract object * from QVariantList:

    but i have lots of errors when i try to build

    The compiler's correct. You'd want to declare the Job * as metatype, not the actual Job. The latter can't be copied. Something's rather fishy, however. Put a qDebug() in your Job's destructor. I'm pretty sure the object gets deleted before you take the pointer to it out of the variant ...



  • @kshegunov said in extract object * from QVariantList:

    deleted before

    no, it is not deleted before, i delete it just after. it looks ok.
    i mean if i let my code like this
    (without calling canConvert()) everything seems to work correctly, all the tests will pass

    void testConnectToHost(){
             machine->connectToServer("opc.tcp://127.0.0.1:4840",0);
    
            QTest::qWait(2000);
            QVERIFY(machine->connected());
        }
    
        void testAddProgram(){
            machine->addProgram("file.ext","C:/Users/Public/prog/AMG1/file.ext",0,0);
            QVERIFY(machine->selectedPrograms().count()==1);
            QVERIFY(machine->selectedPrograms().at(0)!=NULL);
        }
    
        void testAddedProgramValidity(){
                Job * j = (Job*)machine->selectedPrograms().at(0).value<Job*>();
                QVERIFY(j->nom() == "000TestGCODE.nc");
               }
    
        void testDeleteProgram(){ // destructors code executed after this
            machine->deleteProgram("000TestGCODE.nc",0);
            QVERIFY(machine->selectedPrograms().count()==0);
        }
    

    destructor code in case :

      ~Job(){         
            qDebug()<< "deleting Job";
             qDeleteAll(m_outils.begin(), m_outils.end()); 
             m_outils.clear();
        }
    
    private : 
    QList<Outil*> m_outils;
    
    

  • Moderators

    @LeLev said in extract object * from QVariantList:

    (without calling canConvert()) everything seems to work correctly, all the tests will pass

    Well, how does canConvert() change the outcome? Or do you mean you get false from it?


Log in to reply