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);
Related
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
Let's assume we have the following class A:
class A
{
public:
void sum(int x);
};
And we have a function f, which gets a C-style callback with one parameter of type int and calls it:
typedef void (*Callback)(int);
void f(Callback cb)
{
cb(5);
}
Is there any way in C++ to curry a method A::print on an object of type A and pass it to the function f? Something like this:
void main()
{
A a;
auto curry_a = ??; // something like curry_a = [&](int x) { a.sum(x) };
f(curry_a);
}
std::bind and lambda-function are not a solution, because they create objects of type std::function<> with overloaded operator(). It looks like currying in C++, but it cannot be used in my case. I need a real function pointer, i.e. generate code in real time.
You are out of luck, it can't be done in a satisfactory way: The only thing that is exactly a C-compatible function pointer is a function (or class-function but not instance function).
So, you'd have to create a function that fixes a parameter, like the this of a member function. The only way to set this parameter is through a global variable:
A *instance;
void (A::*a_fun)(int);
void applicator(int arg) { instance->*a_fun(arg); }
//...
int main() {
A a;
instance = &a;
a_fun = &A::sum;
f(applicator);
// ...
That is the only way to provide context to a plain function, through global variables.
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 have C framework that provides classic deferred callback execution API:
typedef void (*callback_t)(int value_1, int value_2, void* arg);
void schedule(callback_t callback, void* arg);
Here arg is arbitrary value specified by user that will be passed to the callback and other callback parameters are passed by framework. But really only last argument is used in handlers and it has to be explicitly cast from void*.
Thinking of how callback signature may be changed to match the real one I got to this solution:
template <typename TArg, void (*Callback)(TArg*)>
void run(TArg* arg)
{
schedule([](int, int, void* arg)
{
Callback((TArg*)arg);
}, arg);
}
...
void handler(int* arg) // instead of handler(int, int, void* arg)
{
}
...
run<int, handler>(arg); // instead of schedule(handler, arg)
The only problem here is that callback argument type has to be explicitly specified at run invocation.
Is there a way to make the compiler to deduce this type?
Ideally the execution code should be just:
run<handler>(arg);
There is another solution to initial problem - to create custom function object and pass it as user argument to native API. Then unpack it from void*, execute real callback and delete function object. But there are issues with action cancelling when callback is not executed. It will require much more work to be implemented correctly and I prefer to ignore it if there is a more simple way.
Every once in a while the Preprocessor actually can come in handy:
#define myRun(fun, arg) (::run<::std::remove_pointer_t<decltype(arg)>, fun>(arg))
Note that this will not evaluate arg or fun multiple times. The result is also a parenthesized expression (and not something more icky like a declaration) and thus behaves just like an ordinary function call.
Different approach using std::bind (couldn't test though):
typedef void (*callback_t)(int value_1, int value_2, void *arg);
void schedule(callback_t callback, void *arg)
{
}
template <typename TArg>
void run(void (*Callback)(TArg *), TArg *arg)
{
// needs to be freed
std::function<void()> *bound = new std::function<void()>(std::bind(Callback, arg));
schedule([](int, int, void *arg)
{
std::function<void()> &f = *(std::function<void()> *)arg;
f();
}, bound);
}
void foo(int *a)
{
}
int main()
{
int *arg = nullptr;
run(foo, arg);
}
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
}