C++: Callback in class - c++

I have a bit complicated class.
In this class I have a reference:
Private:
IEtApiPtr _pIEtApi;
IEtApiPtr is defined in a .tlh file:
_COM_SMARTPTR_TYPEDEF(IEtApi, __uuidof(IEtApi));
IEtApiPtr has a void named "SetRawDataCB"
virtual HRESULT __stdcall SetRawDataCB (
/*[in]*/ long address,
/*[in]*/ long userData,
/*[out,retval]*/ enum ApiError * pRetVal ) = 0;
I have defined a callback function in the class:
void CETAPI::RawDataCB(RawData& r, void* userData)
{
//do something
}
Now I want to install a callback using
_pIEtApi->SetRawDataCB((long)(__int64)(&RawDataCB),0,&result);
... the compiler tells me "Error C2276: Invalid operation for expression of a bound member function".
What did I do wrong here?

This doesn't work because RawDataCB is a member function not a global function. You can declare RawDataCB as a static function in the class as follows and this will work. However you will no longer have access to the this pointer (i.e. no member variables) unless you add it as a parameter to RawDataCB and perhaps make RawDataCB a friend to gain access to private data of the class as a member function would have. This can be done by updating the function declaration as follows:
class CETAPI {
static void RawDataCB(RawData& r, void* userData);
};
Alternatively, you can pass a pointer to RawDataCB as a member function pointer rather than a function pointer. Member function pointers can be manipulated as follows, so you will just pass an object of type RawDataCBType to SetRawDataCB.
typedef void (CETAPI::*RawDataCBType)(RawData&, void*); // typedef the member function pointer type
RawDataCBType pmf = &CETAPI::RawDataCB; // create and initialize a pointer to the member function
pCETAPIObject->*pmf(r, userData); // call the member function on an object of type CETAPI
Here is a good article that talks about member pointers.

In This case compiler founds problem in the syntax
use following line of code
pIEtApi->SetRawDataCB((long)(_int64)(&CETAPI::RawDataCB),0,&result);
see the link for more info Error code description

Related

Pass member function as function pointer to argument

Here is my Code:
I want to use a class inside my custom MyStateMachine. I do not want to inherit de StateMachine class as I just want to use it with its functions. The MyStateMachine class is only to encapsulate a few things.
MyStateMachine.h
#include <StateMachine.h>
class MyStateMachine {
public:
void Initialisation();
private:
StateMachine machine = StateMachine();
State* m0Initialisation = machine.addState(&Initialisation); // problem here
};
MyStateMachine.cpp
#include "MyStateMachine.h"
void MyStateMachine::Initialisation() {
// do initialisation stuff here
}
machine.addState expects a function pointer as argument:
State* addState(void (*functionPointer)());
I get the following error message:
error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)())
note: State* StateMachine::addState(void (*)())
State* addState(void (*functionPointer)());
note: no known conversion for argument 1 from 'void (MyStateMachine::*)()' to 'void (*)()'
Compilation error: no matching function for call to 'StateMachine::addState(void (MyStateMachine::*)())'
If I define the function outside the class, I can successfully pass this function as a function pointer (&Initialization).
I guess it has something to do that it is a function of a class and it needs the reference to the object. But even with that I did not find a solution.
How could I pass the function? If possible without external libraries (e.g. std::bind).
I have looked at a few posts but could not find a proper solution.
pass-an-objects-member-function-as-argument-function-pointer
class-member-function-as-function-pointer
using-pointers-to-member-to-pass-member-function-as-arguments
There is some different solutions to your problem.
1: Change the type of your funciton pointer in Statemachine::addState(...) to be a function pointer to a member type instead of a function pointer to a non member function.
Check out section "Pointers to members" here
2: Use std::function as the type of addState and do
State* m0Initialisation = machine.addState([this]() {Initialisation(); });
3: Change Initialization to be static and send in a pointer to your class every time you call the function.
static void Initialisation(StateMachine &self);
The problem is that StateMachine::addState expects a normal function pointer, which is different from a member function pointer. You can make your Initialization function static. Then the member function pointer is essentially a normal function pointer:
struct State {};
struct StateMachine {
State* addState (void (*)()){ return nullptr; }
};
class MyStateMachine {
public:
static void Initialisation();
private:
StateMachine machine = StateMachine();
State* m0Initialisation = machine.addState(&Initialisation); // no problem here
};
Member functions always have an implicit first argument, which is a pointer or reference to an instance of the class. This is the main difference between a normal function pointer and a member function pointer. So taking the implicit argument into account, the member function is not a void nullary function with signature `void (*)(). Static member functions do not have an implicit first argument, so member function pointers to static member functions can be treated like normal function pointers.

Passing C++ class member function as a paremeter to C function

I am using a c dll in a c++ class. One of the member functions should call the following function that generates an interrupt and calls a service routine:
signed short __stdcall SetIrqConditions
(
signed short DevNum,
unsigned short bEnable,
unsigned int dwIrqMask,
void (__stdcall * funcExternalIsr)
(
signed short DevNum,
unsigned int dwIrqStatus
)
);
I am trying to call another member function of the same class as the last parameter of this function.(funcExternalIsr) When I tried to do this, the compiler complained that the function is not static. So I defined the callee function as a static function, but when I do that I cannot access other members of the class.
class myClass
{
public:
int counter;
void func1();
static void __stdcall func2(signed short DevNum, unsigned int Status);
};
void myClass::func1()
{
...
Result = SetIrqConditions(DevNum, TRUE, Mask, func2); --> no error here once func2 is static
}
void myClass::func2(signed short DevNum, unsigned int Status)
{
counter++; --> invalid use of member 'counter' in static member function
}
I tried many different ways and did some research but I can't seem to get this working, any pointers in the right direction would be appreciated.
Passing C++ class member function as a paremeter to C function
There is no way to do this with a non-static function, because C doesn't have such thing as a pointer to member function. C has only pointers to functions, and those cannot point to non-static member functions.
What you can do instead is to write a separate free wrapper function (or a static member function) where you call that non-static member function. Example:
void wrapper_function(demo args)
{
instance.member_function(args);
}
The remaining question is where to get the class instance to call within the wrapper. The options are in general:
Pass it as an argument to the wrapper. This is quite often an option with well designed C style callbacks that have a void* argument. That appears to not be the case here.
Use a variable with static storage. This is not ideal because global state is evil.
Create a local automatic variable within the wrapper. This is often not useful when the state of the instance needs to be accessed elsewhere.

Point a typedef function to another function in another class

I have this typedef function on Class A.h:
typedef void(*PERCENTAGE_CALLBACK)(float);
And I am using on one of the class' function:
int API_GenerateLayerData(int layerIndex, unsigned char *data, int dataSize, PERCENTAGE_CALLBACK callback);
In Another Class (ClassB.cpp), I have this function that returns nothing(void) but accepts a float value just like PERCENTAGE_CALLBACK:
void ClassB::Update(float progress)
{
emit ChangeProgress((int)progress);
}
But when I initialize the PERCENTAGE_CALLBACK object to be used and passed on the function in the ClassA it throws an error:
public void someFunction()
{
ClassA *a = new ClassA();
PERCENTAGE_CALLBACK callback = &ClassB::Update; //Error: cannot convert void ti PERCENTAGE_CALLBACK
a->API_GenerateLayerData(someNum, someData, count, callback);
}
How do I initialize the Class A's callback that points to the Class B's Update Function?
You simply can't do that because calling a member function also needs a object on which the member should be called.
If your api only provide a function pointer, independent of which signature it is, you can't work around this problem even not by std::bind nor by using lambda functions. Both of them are also "callable" objects and as this, they also need a object pointer or reference for the callback.
If you are able to change your API you are using, you should change the callback registration to std::function. std::function is able to handle plain function pointers and also lambdas or any other combination of object/method combination.

pass a function pointer between classes

I have two claces.
here is the first one
class one{
one(){ }
public:
void change(double a){
//print a
}
void run(){
two tw;
tw->functionpointer=&change;
}
};
and here is the two class
public two{
two();
static void progresschange(double v){
functionpointer(v);
}
public:
void (*functionpointer)(double);
};
as you see in example I have a function in class one, I want to call it from an static function in class two As progresschange is static I can only call change function in class one uisng function pointers. but It does not work and compiles says
error: cannot convert ‘void (one::*)(double)’ to ‘void (*)(double)’ in assignment
it happens in this line
tw->functionpointer=&change;
how can I make it work. it is even possible to pass a function using its function pointer to another class using this method?
thanks
The error message is quite straightforward:
error: cannot convert void (one::*)(double) to void (*)(double) in assignment
void one::change(double) is a member function of the class one, not just a function. Therefore, you can't assign a pointer to this member function (i.e.: void (one::*)(double)) to a pointer to a function with the same signature (i.e.: to a void (*)(double)).
Besides, a non-static member function (like one::change() above) has to be called on an object, so you also need to provide an one object to call that pointed-to non-static member function.
Basically, you can achieve what you want by adding the following data members in two:
void (one::*mem_func_ptr)(double);
one *obj_ptr;
That is, a pointer to the member function (mem_func_ptr) and a pointer to the object to call this member function on (obj_ptr).
To assign to the member function pointer:
mem_func_ptr = &one::change;
Then, to call the member function pointed by mem_func_ptr on the object pointed by obj_ptr with 0.0 as argument:
(obj_ptr->*mem_func_ptr)(0.0);
It can be done analogously by keeping a copy of an object one as data member instead of a ponter. In that case you should use the operator .* instead of ->*.
The problem is that one::change() is a class member so you need to pass a pointer to a class instance as well.
The modern way to do it is to use std::function, std::bind and std::mem_fn:
class two {
....
std::function<void(double)> functionpointer;
}
tw->functionpointer = std::bind(std::mem_fn(&one::change), _1, one_instance);
Alternatively you can use a lambda function:
tw->functionpointer = [&one_instance](double x) { one_instance->change(x); }

c++ error: invalid use of member 'calls_object::OBJECT' in static member function

I got the following error from the code below.
error: invalid use of member 'calls_object::OBJECT' in static member function|
error: from this location
from the line OBJECT->call(); line 29.
Basically the function must be static because its really a simplified version of the code
which creates a windows thread. I just can't seem to use pointers within a static function but I can create the object within the static function no problem. Is there another way?
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)windowsthread, (LPVOID)i, NULL, &m_id);
static DWORD_PTR WINAPI windowsthread()
{
OBJECT->call();
}
l
class object
{
private:
public:
object(){}
~object(){}
void call(){}
};
class calls_object
{
private:
object* OBJECT;
public:
calls_object()
{
OBJECT = new object();
}
~calls_object(){}
#ifdef _WIN32
static void windows_function()
{
OBJECT->call();
}
#endif
};
int main()
{
calls_object O;
}
This function:
static void windows_function()
{
OBJECT->call();
}
Is declared as static. It means it does not receive an implicit this pointers: in other words, it does not operate on an instance of calls_object. Therefore, it cannot see the OBJECT member variable.
Either declare the function as non-static, or declare OBJECT as a static member variable (whatever makes more sense in your application).
Basically the function must be static because its really a simplified version of the code which creates a windows thread
Since you are (unfortunately) dealing with a function (CreateThread) that accepts a function pointer, you cannot even use std::bind. However, CreateThread lets you provide a function which accepts a pointer (to void, see the prototype of ThreadProc).
Just pass a pointer to an object as the fourth argument to CreateThread, and let windowsFunction(void*) receive that pointer. Inside windowsFunction(), which would still be static or global (in fact, you do not need the calls_object class at all), you can cast that pointer to a pointer to object and invoke call() on it.
Also notice, that your class calls_object is leaking memory, since you are forgetting to delete the pointer you created in calls_object's constructor:
~calls_object()
{
delete object; // DON'T FORGET THIS!
}
windows_function is a static member function, so is not associated with any calls_object object. OBJECT is a non-static data member, so is associated with a calls_object object. You cannot access a non-static data member from a data member.
Simply make the function non-static and it will work.
Think of it this way. If you didn't even create an object of type calls_object and your main function was just:
int main()
{
calls_object::windows_function();
}
Where would you expect this function to get OBJECT from? Since OBJECT is a non-static member, it only exists as part of a calls_object object. A static member function cannot simply pull OBJECT from nowhere.