I have the following class
class msg{
//other stuffs before
void (*callback)(void *);
bool callback_check(const msg_type_e, void callback);
}
the idea is basically to call "callback_check" function to see whether the "callback" is already set by the client. If it is set, then the callback_check will do internal processing, that is why I thought of passing the "callback" as a parameter for "callback_check" function.
However when I tried to compile it, it complains that "callback has incomplete type". What is the best way to check if a callback has been set or not? How to improve the code above?
thank you
The type void basically means "nothing". And you can't have an argument to a function which is nothing. You have to give it a proper type.
If it's supposed to be the actual callback function, then declare it as a function pointer, e.g.:
bool callback_check(const msg_type_e, void (*callback)(void*));
However I would recommend you to use std::function instead, because then you can pass all kind of functions (like lambdas, member function with the help of std::bind or other callable objects that matches the signature):
bool callback_check(const msg_type_e, std::function<void(void*)> callback);
Of course you should then make the callback member in the class also be a std::function object.
Now to check if a std::function object have a valid callable "function" assigned to it, the class has a boolean operator so it can be used in boolean expressions. Like:
if (this->callback)
{
// Callback should be callable
this->callback(...);
}
Perhaps you meant something like this?
class msg{
typedef void (*callback_t)(void *);
bool callback_check(callback_t callback);
};
void callback attemtps to declare a parameter of type void (unrelated to the callback function pointer you declared previously), which is illegal.
void (*callback)(void *); is a member declaration of type pointer to function. If that was your intention, you don't need to pass it to member function. You could do:
class msg{
void (*callback)(void *);
bool callback_check()
{
return callback != nullptr;
}
};
Your callback parameter is just plain wrong. It should look this this:
class msg{
//other stuffs before
typedef void (*callback)(void *);
bool callback_check(const msg_type_e, callback cb);
}
Parameter types of void don't mean a thing. They are not legal. The only place you can use void in a parameter list in C is when you want the function to take no parameters at all void myfunc(void) means that there will be no parameters.
A type you can pass to a function is void* which is a pointer to void, meaning that the type that is pointed to has no type associated with it. Note that a pointer to void is something completely different to void by itself.
Related
I'm trying to define a function/method (void MyClass::myDispatcher(int, int, void *) or std::function<void(int, int, void *)> myDispatcher) which would be a member of a host class.
However, I also need to pass this function to through an external library which takes as argument: void (*dispatcher) (int, int, void *).
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
My first attempt with the candidate void MyClass::myDispatcher(int, int, void *) was using the std::bind() in order to bind MyClass::myDispatcher with this. Although I could not convert the return type of std::bind to match the void (*).
The second attempt was done using std::function<void(int, int, void *)> myDispatcher for which I tried to use the reinterpret_cast<void (*)(int, int, void *)>(&myDispatcher) to fit in the requested argument. It did compile but I ultimatly ended up in a segfault within the external library.
I could summarized my two attempts with this example:
class MyClass{
MyClass() = default;
void myDispatcher(int, int, void *){
// do something
}
void init(){
myFct = [this](int, int, void*){
// do something
};
external_function(reinterpret_cast<void (*)(int, int, void *)>(&myFct));
// or the non-compiling
// external_function(std::bind(&MyClass::myDispatcher, this));
}
private:
std::function<void(int, int, void*)> myFct;
};
Edit:
As some of you pointed out: this C-style external_function has an extra void * argumement which is passed as the last arg to the provided function!
To summarise: there is no way to do such a thing since there is a fundamental difference between a function pointer and non-static member functions. However, C-style library usually provides a workaround which performs a callback to the provided static function:
void external_function(void (*dispatcher) (int, int, void *), void* info){
// a bunch of instructions (meaningless for this example)
int a,b;
dispatcher(a,b,info);
}
Once we know that, one can cast back the info pointer to the class we want.
As stated, this is not possible since there is no way to meaningfully construct a plain function pointer from a (non static) method, a closure, or a std::function object.
Roughly speaking, each of the constructs above are logically formed by two parts: some fixed code (a pointer to a fixed, statically known function), and variable data (the object at hand, or the captures for a closure). We can not simply throw away the second part.
That being said, I would recommend to check if the library will call the dispatcher passing a user-defined pointer for its void * argument. It's somewhat common to see C style library functions like
void register_callback(void (*dispatcher)(int,int,void *), void *user_data);
This is a trick to allow to simulate closures in C, passing the two "parts" of the closure separately.
If that's the case, instead of
// not working, just for example
std::function<void(int, int)> f;
register_callback(f);
You can write
// Make sure f will live long enough.
// I'm using new to stress the point, but you can use anything
// else provided that the pointer will be valid when f is
// called.
std::function<void(int, int)> *pf = new ...;
register_callback(call_the_function, pf);
provided you have defined
// fixed function, independent from the std::function object
void call_the_function(int x, int y, void *p) {
std::function<void(int,int)> *pf =
(std::function<void(int,int)>*) p;
(*pf)(x,y);
}
If you used new to keep the pointer valid long enough, remember to delete it when the callback is no longer needed.
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
No, there isn't. A function pointer cannot point to non-static member functions, nor to function wrapper objects.
What you can do, is point to a normal function that in turn calls the member function. The challenge is getting the instance into that function. Most C callback API allow passing user defined data into the callback in form of a pointer to void, in which case this isn't a problem. If there is no such option, then you can only use a globally accessible instance, or an instance that is created within the callback.
You will need to read the documentation of the API to find if and how passing user data is possible. There is a void* parameter in the callback, which hints that it may be what you need.
No you can't get a void (*)(int, int, void *) from a non-static member function. Non-static member function are fundametally different from free functions: You need an object to call the method.
However, in your code you are already using std::function and std::function has a constructor to convert a void (Foo::*)(int, int,void*) to a std::function<void(Foo*,int,int,void*)>.
The external library expects a C style function pointer. I't won't accept C++ callable objects (e.g. std::function or std::bind). You have to wrap the C++ callable objects inside a plain function with the required signature. Something like this:
void dispatcher(int theInt1, int theInt2, void *theData) {
theInstanceOfMyClass.myDispatcher(theInt1, theInt2, data);
}
You might want to pass the address of your C++ instance as the third argument, e.g.:
void dispatcher(int theInt1, int theInt2, void *theData) {
static_cast<MyClass *>(theData)->myDispatcher(theInt1, theInt2, data);
}
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.
I'm trying to make a class method that takes a function pointer (regular C function pointer, not a class method pointer) as a parameter. The only thing that comes up when I search is how to create/use a member function pointer, which I'm NOT trying to do. So here's a method that takes a function pointer that returns a bool and takes two ints as parameters:
class ExampleA
{
public:
void sort(WHAT_GOES_HERE); // Should it be the same as method definition below?
};
ExampleA::sort(bool (*customSort)(int, int)) // Hopefully this is correct
{
// Use function pointer
}
Is there a way to declare the parameter in the method declaration without naming it like a method with an int parameter?
class ExampleB
{
public:
void someFunction(int); // Not named here
};
ExampleB::someFunction(int varName)
{
// do whatever
}
Yep! Just leave out the name.
void sort(bool (*)(int, int));
bool (*)(int, int)
Basically, remove the name of the variable to get a declaration without a variable name.
However, you are often better off with a typedef:
typedef bool(*custom_sorter)(int, int);
class ExampleA {
public:
void sort(custom_sorter);
};
ExampleA::sort(custom_sorter customSort) {
// Use function pointer
}
which is equivalent.
As I personally hate the syntax to declare a function pointer, in C++11 I might do:
template<class T> using type=T;
...
void sort(type<bool(int,int)>*)
which puts the signature type together, then I put a * after it to make it a pointer.
But I'm strange.
The declaration should match the definition, so WHAT_GOES_HERE should be bool (*customSort)(int, int), and also the function definition should have the return type void specified.
You can optionally leave out the name customSort, it makes no difference.
This is somewhat inflexible; consider making it a function template that accepts a functor or a std::function instead of a function pointer; then your callers can call it with a wider range of functions.
Comment: I'm posting this question again, since some people requested me to post the full code. Here it is:
I have a function pointer typedef that looks like this:
template<typename USER_DATA>
class RowProcessor
{
typedef void (*RowFunction)(USER_DATA, std::vector<USER_DATA> &);
RowProcessor(RowFunction, int) {};
};
and then I'm using in another class UseRowProcessor:
class UseRowProcessor {
public:
void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
void UseRowProcessor::AddUserData(SomeClass c, std::vector<SomeClass> &v) {
v.push_back(c);
}
void UseRowProcessor::LoadUserData() {
RowProcessor<SomeClass> myRowProcessor(AddUserData, 1); // ERROR!!
}
So the error occurs when calling RowProcessor's constructor.
The full error message says that
no insatnce of constructor "RowProcessor<USER_DATA>::RowProcessor [with USER_DATA=SomeClass]" matches the argument list
argument types are: (void (SomeClass c, std::vector<SomeClass, std::allocator<SomeClass>> &v), std::vector<SomeClass, std::allocator<SomeClass>>)
, which I have no idea what it says except for the fact that the constructor arguments do not match..
Why doesn't my AddUserFunction match the function pointer typedef??
TEST LINK<<<<<<<<
Change the function:
void AddUserData(SomeClass, std::vector<SomeClass> &);
to static void AddUserData(SomeClass, std::vector<SomeClass> &); .
As it is a class member function, the this parameter will be added after compiler, so it is not the type of the function pointer. By changing it to static, no this parameter will be added.
As Matt said you need a static function to get this working
class UseRowProcessor {
public:
static void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
Here's the completely fixed sample (there were some more issues after fixing to static).
Member functions are different from ordinary functions and this carries over to their type. There is a set of work-arounds that enable you to pass member function pointers to functions that take ordinary function pointers as their parameters, but if you have control over the code you should take a different path. Instead of accepting a function pointer accept a functor.
template<typename Functor>
int f(Functor func) {
// use func like you would a function, e.g. call it with arguments func(1, 2)
}
Now you can call f with a lambda, function object, member function pointer (after you bound it to this), or function pointer.
If you want to avoid templates, accept a std::function instead, but this should only be done if you have special reasons for it.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Using a C++ class member function as a C callback function
I'm writing an object-oriented library using a C library (winpcap). I need to pass the callback function that is called when a network packet arrives as a function pointer. I would like to pass a member function pointer to winpcap, to keep my design object oriented and to allow for different objects to receive different packets. However member functions as far as I understand have a different calling convention, and thus cannot be passed to a C function. Is there a way to fix this. My experiments with boost::bind (which I hardly manage to use other than trial and error) are not fruitful.
Is there a way to change the calling convention of a member function?
This is the definition of the callback function I use now and the actual passing of it to winpcap
void pcapCallback( byte* param, const struct pcap_pkthdr* header, const byte* pkt_data );
pcap_loop( adhandle, 0, pcapCallback, NULL );
The pcap_loop just takes the name of the function (which is on the global scope at the moment). This is the definition of the function pointer parameter (3rd parameter of pcap_loop). Since this is third party code I can't really change this. I would have to have a member function that can take this form:
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *);
As far as I understand it, the member function will be using thiscall and the c function pointer wants a cdecl
Kindly refer to detailed topic about
How to Implement a Callback to a static C++ Member Function ?
How to Implement a Callback to a non-static C++ Member Function ?
http://www.newty.de/fpt/callback.html
You can only pass static member functions to a C API.
If you want to have a C API call a member function, you have to pass two pieces of data: the (static member) function and the object for which it is to be invoked.
Usually, C API callbacks have some form of "user data", often a void*, through which you can tunnel your object's address:
// Beware, brain-compiled code ahead!
typedef void (*callback)(int data, void* user_data);
void f(callback cb, void* user_data);
class cpp_callback {
public:
virtual ~cpp_callback() {} // sometimes needed
void cb(int data) = 0;
callback* get_callback() const {return &cb_;}
private
static void cb_(int data, void* user_data)
{
cpp_callback* that = reinterpret_cast<my_cpp_callback*>(user_Data);
that->cb(data);
}
};
class my_callback {
public:
void cb(int data)
{
// deal with data
}
};
void g()
{
my_callback cb;
f(cb.get_callback(), &cb);
}
That pcapCallback doesn't look as if it has user data, though, unless that's what param is. If that's indeed the case, you'll have to store the callback object's address in some global variable before calling the API. Something like this:
// Beware, brain-compiled code ahead!
typedef void (*callback)(int data);
void f(callback cb);
class cpp_callback {
public:
cpp_callback() : the_old_cb_(this) {std::swap(the_cb_,the_old_cb_);}
virtual ~cpp_callback() {std::swap(the_cb_,the_old_cb_);}
void cb(int data) = 0;
callback* get_callback() const {return &cb_;}
private
static cpp_callback* the_cb_;
cpp_callback* the_old_cb_;
static void cb_(int data, void* user_data)
{
the_cb_->cb(data);
}
};
class my_callback {
public:
void cb(int data) { /* deal with data */ }
};
void g()
{
my_callback cb;
f(cb.get_callback(), &cb);
}
As always with global data, this is perilous if more than one instance of the callback is alive. I have tried to minimize the harm so that it works if their lifetimes are nested. Anything else, though, will hurt.