Solved 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 tryJob * 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()));
-
@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
-
@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 ^~~
-
@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 actualJob
. The latter can't be copied. Something's rather fishy, however. Put aqDebug()
in yourJob
'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 passvoid 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;
-
@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 getfalse
from it?