Solved generalize a c++ 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.
-
class MachineBackend : public QObject { typedef void (MachineBackend::*MethodPtr) (QOpcUa::NodeAttribute, const QVariant&); Q_OBJECT public: void uaSub2(QScopedPointer<QOpcUaNode>&node, QString nodeId, MethodPtr updateHandlerPtr){ // trying to use lambda to call my pointed function but can't /* QObject::connect(node.data(),&QOpcUaNode::attributeUpdated,[&]{ (this->*updateHandlerPtr() ) (); }); */ // maybe is it possible to connect to my function directly ? QObject::connect(node.data(),&QOpcUaNode::attributeUpdated,this,&MachineBackend:: ??) } };
-
@LeLev said in generalize a c++ method:
(this->*updateHandlerPtr() ) ();
(this->*updateHandlerPtr) (); <--- You have to pass 2 parameters to it!
-
@jsulm yes but i don't have any parameter to pass to it .. .
its just a handler function that must be connected to
QOpcUaNode::attributeUpdated witch returns 2 values ;that is why it has to have 2 params.
I don't want to call that function, i want it to be connected to
QOpcUaNode::attributeUpdated , and called automatically when attributeUpdated is emitted in the opcua backend
-
@jsulm finally it is this working thanks to you !
class MachineBackend : public QObject { typedef void (MachineBackend::*MethodPtr) (QOpcUa::NodeAttribute, const QVariant&); Q_OBJECT public: void uaSub2(QScopedPointer<QOpcUaNode>&node, QString nodeId, MethodPtr updateHandlerPtr){ QObject::connect(node.data(),&QOpcUaNode::attributeUpdated,this,updateHandlerPtr); } void nIndexUpdated(QOpcUa::NodeAttribute attr, const QVariant &value){ //return; // i can access member variables / signal / methods here } // use uaSub uaSub2(nIndexNode,"ns=4;s=MAIN.nIndex",&MachineBackend::nIndexUpdated); // };
thank you infinitely everybody who helped me