Solved generalize a c++ method
-
@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.
-
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