Solved generalize a c++ method
-
@LeLev said in generalize a c++ method:
@jsulm i think i can not use this last solution, because there is only one instance of this class. it is instantiated in the main.cpp and putted as contextProperty, it is never destroyed and has same life time as my application. I can not create another object of this class
ok, when this - in essence - is a singleton, why don't you make the member variable then also static?
-
because i'm JS guy ... i 'm learning Qt/cpp only for 2 years now.
let me try it -
@J-Hilk said in generalize a c++ method:
why don't you make the member variable then also static?
i have one member variable per subscription,
each member variable has a Q_PROPERTY corresponding to it, so i can use the variable value from QML.is it possible do define Q_PROPERTIES for a static member variable ?
Im trying but getting errors :
moc_machinebackend.cpp:-1: erreur : undefined reference to `MachineBackend::m_url'Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) public: QString url()const{ return MachineBackend::m_url; } void setUrl(const QString nUrl){ if(MachineBackend::m_url==nUrl)return; MachineBackend::m_url = nUrl; emit urlChanged(nUrl); } private : static QString m_url; signals: void urlChanged(QString url);
-
@LeLev said in generalize a c++ method:
i think i can not use this last solution
Sure you can: you pass the pointer to second method when you call the first method, right? And since both methods are not static you call the first method already on an instance (which is "this" inside the method):
this->*method(); // method is the pointer to the other method
-
@jsulm said in generalize a c++ method:
: you pass the pointer to second method when you call the first method, right?
Yes, but it only works if the
2nd method is static !//first void uaSub(QScopedPointer<QOpcUaNode> &node, QString nodeId , void (*theUpdateHandler)(QOpcUa::NodeAttribute attr,const QVariant &value)){...} // 2nd static void nIndexUpdated(QOpcUa::NodeAttribute attr, const QVariant &value){...} uaSub(nIndexNode,"ns=4;s=MAIN.nIndex",*nIndexUpdated){...} //Here **nIndexUpdated** must be static ! no ?
if it is not static i get :
reference to non-static member function must be called error -
@LeLev Please take a closer look at the snippet I provided before:
typedef void (T::*MethodPtr) (); MethodPtr method = &T::MethodA; T *obj = new T(); obj->*method();
Your syntax is not even correct as you have to use & to get a pointer not *
So in your case something likeclass A { typedef void (A::*MethodPtr) (); void nIndexUpdated() {} void uaSub(..., MethodPtr ptr) { this->*ptr(); } // Somewhere inside class A you call uaSub uaSub(/*params*/, &A::nIndexUpdated); }
-
@jsulm
thank you so much for the help you provide.
Unfortunately i'm so bad, i can't make this workclass MachineBackend : public QObject { typedef void (MachineBackend::*MethodPtr) (); Q_OBJECT void nIndexUpdated(QOpcUa::NodeAttribute attr, const QVariant &value){...} void uaSub2(QScopedPointer<QOpcUaNode>&node, QString nodeId, MethodPtr updateHandlerPtr){ this->*updateHandlerPtr(); // < error here } };
called object type 'MachineBackend ::MethodPtr' (aka 'void (MachineBackend ::*)()' ) is not a function or function pointer
-
@LeLev Try
this->updateHandlerPtr();
-
@jsulm said in generalize a c++ method:
this->updateHandlerPtr();
yes i did also, in that case error is :
no member named 'updateHandlerPtr' in 'MachineBackend '
which is true -
@LeLev This should compile:
(this->*updateHandlerPtr)();
Method pointers are a mess :-)
-
yes now it doas. awesome ! thank you so much!
class MachineBackend : public QObject { typedef void (MachineBackend::*MethodPtr) (); Q_OBJECT void nIndexUpdated(QOpcUa::NodeAttribute attr, const QVariant &value){...} void uaSub2(QScopedPointer<QOpcUaNode>&node, QString nodeId, MethodPtr updateHandlerPtr){ (this->*updateHandlerPtr)(); } };
there is still an issue in the usSub() call
// Somewhere inside class uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex", MachineBackend::nIndexUpdated); // << error //
error : reference to non-static member function must be called
im trying every possible syntax right now ...
-
@LeLev said in generalize a c++ method:
uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex", MachineBackend::nIndexUpdated);
uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex", &MachineBackend::nIndexUpdated);
-
@LeLev This small example works for me:
#include <iostream> class A { public: typedef void (A::*MethodPtr) (); void someMethod() { std::cout << "Hallo!" << std::endl; } void uaSub2(MethodPtr updateHandlerPtr){ (this->* updateHandlerPtr)(); } }; int main() { A a; a.uaSub2(&A::someMethod); return 0; }
-
@jsulm yes sorry that is the first one i have tryed:
uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex", &MachineBackend::nIndexUpdated); // err : cannot initialize a parameter of type 'Machinebackend::MethorPtr' (aka 'void (MAchinebackend::*)()') with an rvalue of type 'void (MAchineBAckend::*)(QOpcUa::NodeAttribute, const QVariant &)' : different number of parameters (0 vs 2) error : no matching function for call to 'MachineBackend::uaSub2(QScopedPointer<QOpcUaNode>&, const char [19], <unresolved overloaded function type>)' uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex",MachineBackend::nIndexUpdated); ^
-
This post is deleted! -
@LeLev said in generalize a c++ method:
nIndexUpdated
This one has parameters, you need to adapt your typedef for the pointer accordingly.
This is what the error tells you. -
class MachineBackend : public QObject { typedef void (MachineBackend::*MethodPtr) (); Q_OBJECT void nIndexUpdated(QOpcUa::NodeAttribute attr, const QVariant &value){...} void uaSub2(QScopedPointer<QOpcUaNode>&node, QString nodeId, MethodPtr updateHandlerPtr){ (this->*updateHandlerPtr)(); } };
in the constructor of this class i call m_client.connectToServer(), then connect stateChanged signal of the m_client to a method where i want to create the subscriptions :
QObject::connect(m_client.data(), &QOpcUaClient::stateChanged, this, &MachineBackend::clientStateHandler);
void MachineBackend::clientStateHandler(QOpcUaClient::ClientState state) { setConnected((state == QOpcUaClient::ClientState::Connected)); if (state == QOpcUaClient::ClientState::Connected) {// if client is connected i create subscriptions // uaSub(nIndexNode,"ns=4;s=MAIN.nIndex",*nIndexUpdated); // function pointer to static function // uaSub1(nIndexNode,"ns=4;s=MAIN.nIndex", MachineBackend::NINDEX) // enum uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex",&MachineBackend::nIndexUpdated); } [...] }
I think i have to adapt my typedef because &QOpcUaClient::stateChanged returns 2 parameters
-
@LeLev said in generalize a c++ method:
I think i have to adapt my typedef
Yes, you have to specify the parameter types when defining a function/method pointer type.
-
i'm having troubles to adapt the typedef..
should it betypedef void (MachineBackend::*MethodPtr) (QOpcUa::NodeAttribute attr,const QVariant &value); or typedef void (MachineBackend::*MethodPtr(QOpcUa::NodeAttribute attr,const QVariant &value)) ();
-
@LeLev said in generalize a c++ method:
typedef void (MachineBackend::*MethodPtr) (QOpcUa::NodeAttribute attr,const QVariant &value);
typedef void (MachineBackend::*MethodPtr) (QOpcUa::NodeAttribute, const QVariant&);
No need for parameter names, only types.