I have a class Myclass:
in Myclass.h file:
class{
private:
int sd;
int sd2;
public:
void func(int sd, short op, void *ptr);
void start();
};
in Myclass.cpp file:
void Myclass::start(){
struct arg_t *arg = (struct arg_t *)malloc(sizeof(struct arg_t));
....
event_set(ev, sd, EV_READ, call_func, arg ); //this is a library API, which trigger the callback of call_func(sd, op, arg);
}
void Myclass::func(int sd, short op, void *ptr)){
...
if(some_conditions){
struct arg_t *arg = (struct arg_t *)malloc(sizeof(struct arg_t))
....
event_set(ev, sd2, EV_READ, call_func, arg );
.....
}
...
}
in main.cpp
int main(){
Myclass obj;
....
obj.start();
....
}
in start(), the event_set need a function of void(*func)() type as argument,but func() is of void Myclass::(*func)() type, so I define a new function something like below (the codes are not correct, but just show what I expect):
void call_func(int sd, short op, void *ptr){
Myclass::func(int sd, short op, void *ptr);
}
however, I'm at a loss where to delcare and define call_func() so that the Myclass::start() can use call_func as argument and call_func() can call Myclass::func()
This is a known problem. Since pointers to class members are not regular pointers, one can not use class member functions in naive callbacks, which expect a simple function pointer.
A solution is to make a callback function static, often private, and call the corresponding class function using the callback argument. In your case, it would look like following:
class C {
private:
int sd;
static void call_func(int sd, short op, void* ptr) {
C* obj = static_cast<C*>(ptr);
obj->func(sd, op);
}
public:
void func(int sd, short op);
void start() {
event_set(ev, sd, EV_READ, &call_func, this);
}
};
EDIT
Fixed messed up start() and func().
I'm at a loss where to delcare and define call_func() so that the Myclass::start() can use call_func as argument and call_func() can call Myclass::func()
You can put this all in your Myclass.cpp file, above the definition of Myclass::start().`
#include <Myclass.h>
void call_func(int sd, short op, void *ptr){
Myclass::func(int sd, short op, void *ptr);
}
void Myclass::start(){
event_set(ev, sd, EV_READ, call_func, NULL ); //this is a library API, which trigger the callback of call_func(sd, op, NULL);
}
void Myclass::func(int sd, short op, void *ptr)){
...
...
}
One other thing, with callback functions, the void* ptr is how you can pass a pointer to some data that the callback function will use. If you don't need anything like that then you don't need to be calling a non-static member function as the callback and you could simplify things. But to call non-static member function the way you're describing, you need an object to call it on, and that's what you would pass as the void *ptr:
// Myclass.h
class Myclass {
private:
int sd;
public:
void func(int sd, short op); // no void*
void start();
};
// Myclass.cpp
#include <Myclass.h>
void call_func(int sd, short op, void *ptr){
assert(ptr != NULL);
static_cast<Myclass *>(ptr)->func(int sd, short op); // cast data to 'this' pointer
}
void Myclass::start(){
event_set(ev, sd, EV_READ, call_func, this ); // pass the 'this' pointer as data
}
void Myclass::func(int sd, short op)){
...
...
}
the last argument of event_set() is still needed to be used for a pointer to an additional structure, so it can't be this
You need to pass this somehow or you can't call a member function, so if you have another structure you need to think about how to pass both.
Can the other structure or a pointer to it be a member of the object? If so, then do that and pass this as the void *ptr.
Another option is to define a struct just for passing the data through the callback:
struct callback_params {
Myclass *c;
other_struct *s;
};
But you have to create this callback_params struct somewhere where it will live long enough for the callback to be able to receive it, which can be tricky.
WRONG ANSWER!!!!
My old tablet didn't load the code sections of the question
correctly and I miss important parts of the question...
Leaving here just as sake of completeness - maybe this can be util
for someone else
SORRY
I don't know the complete stuff that you're doing but in this cases,
if i don't need interface with old code I will go for std::function for sure.
But if is absolutely needed the pointers stuff, I generally do:
Put a very ugly name in the function - So every one will know that this is a 'hack' and not a good thing. ex: _func_call_wrapper_(...)
Put into the top of .cpp file the definition with the appropriated comments and so on. ex:
//This is a wrapper neeeded for...
void __func_call_wrappper_(..);
Finally in the bottom of the .cpp file I define the function, of course,
with a lot of comments of why this is needed.
Refs:
ccpreference
Related
I have a 3rd party library, which has a function requiring a callback function with the following signature:
typedef void (*callback1) (void *data, SomeObj *obj, const char *param0, const char *param1);
There is another function which has a slightly different callback signature:
typedef void (*callback2) (void *data, SomeObj *obj, void *extra);
Now, I don't care about the parameters, I only need the fact that the callback is actually being called, and I don't want to write two separate functions with the same content.
Can I solve this with template somehow?
I tried with the below syntaxes:
template<class... dontgiveas> void mycallback(const dontgiveas&... args);
template<class... dontgiveas> void mycallback(dontgiveas&... args);
template<class... dontgiveas> void mycallback(dontgiveas... args);
template<typename... dontgiveas> void mycallback(dontgiveas... args);
How can I make a single function in C++ which can be called with any number and type of parameters?
Normally, I would define two functions:
void mycallback1(void *data, SomeObj *obj, const char *param0, const char *param1);
void mycallback2(void *data, SomeObj *obj, void *extra);
And I have to pass these to the 3rd party library:
3rd_party_library_function_a(mycallback1);
3rd_party_library_function_b(mycallback2);
The C++ standard allows a function pointer to be explicitly casted to another function pointer type. Though, calling a function via a casted pointer is technically undefined behavior, but since the callbacks in question are using a calling convention, cdecl, that does not require the callee to cleanup any passed parameters (at least in x86, not sure about x64), you should be able to get away with using a parameter-less function and cast it as needed, eg:
void mycallback()
{
cout << "callback called" << endl;
}
3rd_party_library_function_a(reinterpret_cast<callback1>(&mycallback));
3rd_party_library_function_b(reinterpret_cast<callback2>(&mycallback));
Demo
With template, you might do:
template <typename... Ts>
void mycallback(void* data, SomeObj* obj, Ts...)
{
// ...
}
// And then
3rd_party_library_function_a(&mycallback<const char*, const char*>);
3rd_party_library_function_b(&mycallback<void*>);
but simple
void mycallback(void* data, SomeObj* obj);
void mycallback1(void* data, SomeObj* obj, const char*, const char*) { mycallback(data, obj); }
void mycallback2(void* data, SomeObj* obj, void*) { mycallback(data, obj); }
// And then
3rd_party_library_function_a(&mycallback1);
3rd_party_library_function_b(&mycallback2);
seems to do the job.
I have a player class which looks like this (stripped down to what is needed for this problem):
class Player
{
public:
Player();
~Player();
void kill();
void death();
void reset();
};
The kill(), death(), and reset() functions look like this:
void Player::kill()
{
void (*dPtr)() = &death;
Game::idle(dPtr, 48);
}
void Player::death()
{
reset();
}
void Player::reset()
{
//resets
}
The idle function is a static memeber function of Game, which takes a function pointer and an integer n, and calls the function after n tick. Here is the function, the implementation shouldn't matter:
class Game {
static void idle(void (*)(), int);
};
This code gives me the error:
ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Player::death' [-fpermissive]
So I change the line from
void (*dPtr)() = &death;
to
void (Player::*dPtr)() = &Player::death;
to solve that issue. But then my call to the idle function is incorrect, as it takes a regular function pointer, and I am passing in a member function pointer, and thus gives me the error:
no matching function for call to 'Game::idle(void (Player::*&)(), int)'
So my question is:
How can I pass the member function pointer Player::*dPtr into the idle function, which takes a void (*)() as an argument?
Or is there another way I can solve my previous error which forbids me from taking the address of an unqualified member function to form a pointer to a member function?
Another answer mentions that you need two pointers. However C++ already comes with containers for doing just this, so it would make your code a lot simpler to use those. (In C++03, some of the std:: items below were std::tr1::).
Sample code:
#include <iostream>
#include <functional>
struct Game
{
static void idle( std::function<void()> func, int x )
{ std::cout << "x = " << x << "\n"; func(); }
};
struct Player
{
void death() { std::cout << "player.death\n"; }
void kill() { Game::idle( std::bind(&Player::death, this), 48 ); }
};
int main()
{
Player p;
p.kill();
}
Lifetime note: std::bind binds by value. Using *this means a copy of the Player is made and stored in the std::function object, copied around with it as necessary.
Using this means the function object stores a pointer, so if you actually store the function object in Game::idle you must take care that this Player is not destroyed before removing this function object from Game::idle's list.
To call a member function through a pointer, you need two pointers: the pointer to the function itself, and a pointer to an object to be this. Your Game::idle API does not support this usage. You need to change it so that it passes at least one argument (conventionally of type void *) to the callback. Then you can use the following pattern:
struct Player
{
// ...
void kill();
// ...
static void call_kill(void *self);
};
void Player::call_kill(void *self)
{
static_cast<Player *>(self)->kill();
}
struct Game
{
static void idle(void (*)(void *), void *, int);
};
void Game::idle(void (*callback)(void *), void *arg, int ticks)
{
// ...
callback(arg);
// ...
}
void kill_player_delayed(Player *p, int ticks)
{
Game::idle(Player::call_kill, static_cast<void *>(p), ticks);
}
You have to write a static call_X method for every instance method X you want to call.
An alternative approach, which is arguably more C++-idiomatic and flexible, and involves less explicitly written-out code, but has higher runtime costs (three indirect function calls and a heap allocate-free cycle per invocation, instead of a single indirect function call), is to have Game::idle take an object of a particular class, with a virtual callback method. That class is then given a template subclass that can call anything that implements operator(), such as the result of std::bind.
struct Runnable { virtual ~Runnable(); virtual void invoke() = 0; };
template <typename T> struct TRunnable : Runnable {
TRunnable(T target) : target(target) {}
void invoke() { target(); }
private:
T target;
};
template <typename T> TRunnable<T>* make_Runnable(T obj)
{ return new TRunnable<T>(obj); }
struct Game
{
static void idle(Runnable *, int);
};
void Game::idle(Runnable *r, int ticks)
{
// ...
r->invoke();
delete r;
// ...
}
struct Player
{
// ...
void kill();
// ...
};
void kill_player_delayed(Player *p, int ticks)
{
Game::idle(make_Runnable(std::bind(&Player::kill, p)), ticks);
}
You cannot make Game::idle take the result of std::bind directly because that object's type is unspecified (and varies depending on how you call std::bind), so it can only be used as an argument to a template function call. A virtual method call to an adapter class is the only way to keep Game::idle compiled out-of-line and still let it use bound-call objects.
In either approach, beware object lifetime issues. In particular, if Game::idle does not call its callback before returning, you need to
make sure that both the original object, and (in the second approach)
the object returned by make_Runnable survive until the callback fires. This is why make_Runnable uses new.
Because I really don't like the answer that casts void*'s to other objects (almost never necessary in C++!) and nobody has posted an answer using the suggestions in the comments I'm going to suggest this.
Use a templated type for your callback!
Like this:
class Game{
template<typename Func>
static void idle(Func &&func, int i){
// game stuff
func();
// other game stuff
}
};
Then you don't lose all of your type safety (casting void*) and it should be the fastest solution.
Also, where you are assigning a function pointer, you can change the code to be far more readable in this case:
void Player::kill(){
Game::idle([this](){this->death();}, 48);
}
Which is far nicer than having to write the correct function pointer type.
You cannot do that simply because pointer to [static] function is a single pointer sizeof void*. In contrary member function need more information, e.g. two pointers: one for this and another one for the function itself so member function pointer has sizeof > sizeof(void*).
Therefore you have two options:
to change signature of your idle() to this void idle(void (*)(), void*, int); so you will be able to pass this somehow.
Or make static variable that will hold this pointer. But that assumes that only one death() can be at idle queue at any given moment of time.
1) is what people do usually in such cases.
I'm trying to use pthreads with classes. I've read that the best solution to use threads with member functions is to define a static helper function and call the thread function from inside. But this requires a 'this' pointer to be passed as an argument to pthread_create. How do I implement this if my original thread function already has an argument? Is there a way to pass multiple arguments to pthread_create?
pthread_create is defined as
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
So, it takes a function pointer, e.g.
void *myfunction(void *argument)
and the void* argument
If you want to use it in a class, do:
Define a static method with the signature: static void *myMethod(void *argument)
Call pthread_create from an object (non-static) method and pass this as the arg parameter.
The implementation of the static method must cast the void *argument to a pointer of the class (a sort-of-this) that can be used to call other (non-static) methods of the object.
Now, depending of what other things you need to do in the thread and passing arguments to them, you can do several things:
Instead of passing the this in the arg, pass a different type that can contain the this and all the arguments.
Or, perhaps more OO, make those arguments, required by the thread functionaly, attributes of the class that can be set in the object before calling pthread_create and can be got from the sort-of-this
being more specific
class MyThread {
public:
MyThread(int _argument): mArgument(_argument) { }
void start() {
pthread_create(&mThreadId, 0,&MyThreadClass::threadMethod, this);
}
void doThings(int x) {
// something to be done in the thread.
}
static void *threadMethod(void *arg) {
MyThread *_this=static_cast<MyThread *>(arg);
_this->doThings(_this->getArgument());
}
int getArgument() const {
return mArgument;
}
private:
pthread_t mThreadId;
int mArgument;
};
That can be called as:
MyThread thread(10);
thread.start();
You cannot pass multiple arguments to pthread_create, but you can pack multiple arguments into a struct that you create specifically for the purpose of packing the arguments. Make the struct "private" to your implementation by defining it in the cpp file, rather than in the header. Pass a pointer of that struct to pthread_create, then "unpack" it in the helper to call the member function.
Let's assume that the thread implementation is a member function threadRun defined as follows:
int MyClass::threadRun(int arg1, string arg2) {
... // Do useful work
return 42; // Return an important number
}
To call this function, define a thread_args struct like this:
struct thread_args {
MyClass *instance;
int arg1;
string arg2;
};
Now your helper function can be defined as follows:
void* thread_helper(void *voidArgs) {
thread_args *args = (thread_args*)voidArgs;
int res = args->instance->threadRun(args->arg1, args->arg2);
return new int(res); // Return an `int` pointer to pass back thread runner's results
}
The function that starts up the thread could look like this:
...
MyClass runner;
thread_args args;
args.instance = &runner;
args.arg1 = 123;
args.arg2 = "hello";
pthread_t thread_id;
int s = pthread_create(&thread_id, NULL, &thread_helper, &args);
I have the following code snippet of a small Thread class I am trying to implement:
declaration:
template <typename T>
class Thread{
public:
Thread(T*, void (T::*)());
void start();
private:
friend void* createThread(void*);
T* arg; //the object
void (T::*function)(); //the ptr to function in that object of type T
pthread_t thread;
};
And below is a snippet of the definition.
template <typename T>
void* createThread(void *arg){
//get back the pair..
std::pair<T*, void (T::*)()>* p = (std::pair<T*, void (T::*)()>*)arg;
//open up the pair
T& t = *p->first;
void (T::*fn)() = p->second;
//TEST
Temp ttt;
ttt.a=100;
(ttt.*fn)(); //segfaults here..
(t.*fn)(); //and even here
}
template <typename T>
void Thread<T>::start(){
//pair of pointer to object, and the pointer-to-member-function
std::pair<T*, void (T::*)()> p(arg,function);
pthread_create(&thread, NULL, createThread<T>, (void*)&p);
}
In the above code, Temp is a class with a function and a field 'a'. And I get the thread running by the following code:
Temp t;
t.a=11;
Thread<Temp> tt(&t, &Temp::function);
tt.start();
Any idea why the code segfaults? I recollect that pointer-to-member-function does not really go well with casting to void* and back. Is that the case in here (since I am not doing that directly)?
Any pointers/suggestions will be highly appreciated.
Thanks! :)
It is segfaulting because your temporary pair std::pair<T*, void (T::*)()> p(arg,function); is falling off the scope before your createThread function is called.
Store a copy of your pair in a heap memory and pass that.
Then delete the copy inside the createThread function.
EDIT
As an aside, this would probably be better represented using std::functions. Exactly same idea(code even looks similar), but does not force you to rewrite your code for additional arguments. Look at pthread member function of a class with arguments.
MyClass is a singleton class (There will only ever be one of these in my whole program).
What I want to do is follows.
Add data to my class using AddData, get a function pointer returned that I can then pass to 'another' function in a dll.
Then this 'other' function calls my call back function
My class is like so.
typedef void (*DataReceivedCallback)(int, int);
class MyClass
{
MyClass();
~MyClass();
void AddData(int sourceId, DataReceivedCallback &callback);
static void MyCallBackFunction(int var1, int var2);
};
void MyClass::AddData(int sourceId, DataReceivedCallback &callback)
{
callback = &MyCallBackFunction;
}
void MyClass::MyCallBackFunction(int var1, int var2 )
{
//do something blah blah
}
I can then do:
int main()
{
DataReceivedCallback callback;
MyClass->GetInstance()->AddData(1, callback);
callback(1,100);
}
When I step through this I see that I do actually step into the callback MyCallBackFunction which is what I want :)
What I then want to do now is pass this 'callback' defined in main to a dll function that will call back into my callback function.
I have the code for the dll so I want to modify one if its functions so that it accepts my callback function parameter.
I am doing this in the dll function signature:
void * someDllFunction( int var1, int var2, DataReceivedCallback& callback)
{
callback(2, 200);
}
But I get the error:
error C2872: 'DataReceivedCallback' : ambiguous symbol
How can I solve this?
Does this have to do with only being allowed to use c-style parameters across dll boundaries??
typedef void (*DataReceivedCallback)(int, int);
should be,
typedef void (MyClass::*DataReceivedCallback)(int, int);
Because, MyCallBackFunction is a non-static member method of MyClass. So it cannot have regular function signature.
Also change assignment to,
callback = &MyClass::MyCallBackFunction;
Demo.
You got your types wrong. DataReceivedCallback, alias void(*)(int, int), is a function pointer, but &MyClass::MyCallBackFunction is a pointer-to-member-function (PTMF). Those two are entirely unrelated and incompatible types!
You cannot treat a member function as a free function.
Since you only have one single instance of your class (Note: "one instance", not "one class"; you always only have one class), why bother with member functions at all? Just make the function global (inside a namespace) and you're done. Though perhaps I'm misunderstanding your requirements.
Another note: You don't need to pass function pointers by reference to the DLL function, just pass them by value. They're just pointers, so they're light-weight.
The thing you are missing is how to declare a pointer to member function and how to invoke the member function via that pointer, below is a working example based on your example:
class MyClass;
//standard way to declare a pointer to member function should be - className::*memberFunName(para list)
typedef void (MyClass::*DataReceivedCallback)(int, int);
class MyClass
{
public:
void AddData(int sourceId, DataReceivedCallback &callback);
void MyCallBackFunction(int var1, int var2);
};
void MyClass::AddData(int sourceId, DataReceivedCallback &callback)
{
callback = &MyClass::MyCallBackFunction;
}
void MyClass::MyCallBackFunction(int var1, int var2 )
{
//do something blah blah
int tem = var1 + var2; //tem = 3 here
}
int main()
{
MyClass obj;
DataReceivedCallback callback;
obj.AddData(1, callback);
(obj.*callback)(1,2); //standard way to call the member function via function pointer
}