Multiple arguments to function called by pthread_create() - argument is function pointer - c++

My case is similar to another Question.
I would like to pass a function as argument and an integer value. Testing the case with a simplfied construction:
void print (int x, int y)
{ cout << "x = " << x << ", y = " << y << endl; }
void *interrupt (struct arg_struct args);
struct arg_struct {
void (*func)(int,int); // Argument 1
int a; // Argument 2
int b; // Argument 3
};
int _tmain(int argc, _TCHAR* argv[]){
int a = 1700, b = 1000;
struct arg_struct arguments;
arguments.func = print;
arguments.a = a;
arguments.b = b;
(*interrupt)(arguments);
cin.get(); return 0;
}
void *interrupt (struct arg_struct args) {
void (*func) (int,int) ;
func = args.func;
int x = args.a;
int y = args.b;
(*func)(x,y);
return 0; // Erfordert Rückgabewert
}
So now I want to create a thread to execute this passed function.
void *InThread_func(struct arg_struct *); // Prototype
struct arg_struct {
void (*func)(int); // Argument 1
int IntNumber; // Argument 2
};
int InThread(void (*func)(int), int IntNumber){
struct arg_struct arguments;
arguments.func = func;
arguments.IntNumber = IntNumber;
// Initialize handler
pthread_t InThread_thread;
// Create thread
pthread_create(&InThread_thread,NULL,&InThread_func,(void*) &arguments);
pthread_join(InThread_func,NULL);
return(errno);
}
Using
g++-4.6 -o test test.cpp
the compiler says
invalid conversion from void* (*)(arg_struct*) to void * (*)(void*)
referring to the last argument of pthread_create.
Why is that?

C++ is picky when it comes to casting.
Replace void *InThread_func(struct arg_struct *); by void *InThread_func(void *my_data); and it should solve the problem.
Since this is C++ I'd recommend using std::thread is those are available to you.

"Why is that?" Because you have an invalid conversion from
void* (*)( arg_struct* ) to void* (*)( void* ), perhaps. The third
argument to pthread_create (not the last) must be an
extern "C" void* (*)( void* ). (Some compilers will ignore the
necessity of the extern "C". They are broken in this regard.) So
your InThread_fnc (which I can't find in your code) must be something
like:
extern "C" void*
InThread_fnc( void* from_pthread_create )
{
arg_struct const* p = static_cast< arg_struct const* >( from_pthread_create );
(*p->func)( p->IntNumber );
return nullptr;
}
Of course, this only works if the last argument of pthread_create was
a arg_struct*. Which corresponds to your case, but beware if you
start deriving: passing a new Derived or a &someDerived when the
function you start casts to Base* results in undefined behavior.

Related

how can I use c empty parentheses function, in c++?

I have a C library which use this function prototype, I want to use it in C++
int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);
but in reality the function asked is
int funct_ptr(int keycode, void *param);
In fact I have this problem: Why put void in params?
Then, I ask you how can I call this function with the appropriate C++ funct_ptr ?
Or have I to re-compil this lib after having changed the funct_ptr prototype ?
This doesn't work:
mlx_key_hook(win_ptr, [](int keycode, void *param) -> int {
return 0;
}, NULL);
This work but that's not what I want:
mlx_key_hook(win_ptr, []() -> int {
return 0;
}, NULL);
The best solution would be to recompile your C++ code with a header that uses an appropriate function prototype, i.e.
int mlx_key_hook(void *win_ptr, int (*funct_ptr)(int keycode, void *param), void *param);
Then the code snippet with a lambda that takes two parameters will compile.
Another solution would be to use reinterpret_cast. Although it is not allowed to call a function with a reinterpreted signature (undefined behavior) casting a reinterpreted pointer back to its original signature before the call is allowed.
typedef int (*funct_ptr_good)(int, void *);
typedef int (*funct_ptr_bad)();
void foo(funct_ptr_bad fb) {
// This is a C++ version of what your C library does
funct_ptr_good fg = reinterpret_cast<funct_ptr_good>(fb);
fg(12345, NULL);
}
int main() {
funct_ptr_good fg = [] (int key, void * ptr) -> int {
cout << key << " " << ptr << endl;
return 0;
};
// foo expects a pointer that takes no parameters, in the same way that your C library does
foo(reinterpret_cast<funct_ptr_bad>(fg));
return 0;
}
The above prints 12345 0 (demo).

C++ function pointer type is not compatible with candidate on Linux and VMS

This question is related to my another question- boost::bind return a function object which is the argument for a function that requires pointer
Except the interface of
bridge_set_pound_var_func
is not allowed to be changed.
Also, boost::function or boost::bind do not work well with the large project.
My new code is as follows:
#include <iostream>
class myA
{
public:
int bridge_set_pound_var_func(int (*fp)(const char *, char *, void *), void *arg)
{
void * b = NULL;
int a = fp("this is poundVar", "ths is t1", b) ;
std::cout << "bridge_set_pound_var_func is called "<< " , a is " << a << std::endl ;
return 0;
}
};
class myC
{
public:
myA *myOA;
int func(const char * poundVar , char * t1, void * t2);
int myCCall()
{
myA myAO;
myOA = &myAO;
std::cout << "myCCall is called " << std::endl;
myOA->bridge_set_pound_var_func( &myC::func, (void *)this );
return 0;
}
};
int myC::func(const char * poundVar , char * t1, void * t2)
{
std::cout << "myC::func is called " << std::endl;
return 1;
}
int main()
{
myC myCO ;
myC *m1p = &myCO ;
m1p->myCCall() ;
return 0 ;
}
// EOF
The errors on Linux :
In member function 'int myC::myCCall()':
error: no matching function for call to 'myA::bridge_set_pound_var_func(int (myC::*)(const char*, char*, void*), void*)'
candidates are: int myA::bridge_set_pound_var_func(int (*)(const char*, char*, void*), void*)
errors on VMS:
In member function 'int myC::myCCall()':
error: no matching function for call to 'myA::bridge_set_pound_var_func(int (myC::*)(const char*, char*, void*), void*)'
candidates are: int myA::bridge_set_pound_var_func(int (*)(const char*, char*, void*), void*)
The short answer is: pointers to member functions are not pointer to functions. The former need to know about the object they are called on, the latter don't. A typical approach used is to use the usually present "user data" void* to point to a suitable base class, cast the pointer and call a corresponding virtual function. Frim there you can recover the necessary object context easily.

boost::bind return a function object which is the argument for a function that requires pointer

I am doing C++ coding on Linux about boost::bind.
The return data type of boost::bind is a function object, which is an input argument to another function bridge_set_pound_var_func.
But, bridge_set_pound_var_func's input argument must be a function pointer. bridge_set_pound_var_func's interface cannot be changed.
The code is as follows:
#include <boost/bind.hpp>
#include <iostream>
using namespace boost;
class myA
{
public:
int bridge_set_pound_var_func( int (*pound_var_func)(const char *, char *, void *), void *arg ) { std::cout << "bridge_set_pound_func is called " << std::endl ; return 0; }
};
class myC
{
public:
myA *myOA;
int func(const char * poundVar , char * t1, void * t2);
int myCCall() { myOA->bridge_set_pound_func( (boost::bind(&myC::func, this)), (void *)this ); return 0;}
};
int myC::func(const char * poundVar , char * t1, void * t2)
{
std::cout << "myC::func is called " << std::endl;
return 1;
}
int main()
{
myC myCO ;
myC *m1p = &myCO ;
m1p->myCCall() ;
return 0 ;
}
// EOF
I got compile error:
error: no matching function for call to
'myA::bridge_set_pound_func(boost::_bi::bind_t<int (&)(const char*, char*, void*), boost::_mfi::dm<int ()(const char*, char*, void*), myC>, boost::_bi::list1<boost::_bi::value<myC*> > >, void*)'
note: candidates are: int myA::bridge_set_pound_func(int (*)(const char*, char*, void*), void*)
Any help will be appreciated.
And, the interface of bridge_set_pound_var_func cannot be changed because it needs to be called by many other functions.
This is the new code that work. But, "myC::func is called" is not printed, why ?
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
using namespace boost;
class myA
{
public:
int bridge_set_pound_var_func( const boost::function3<int, const char *, char *, void *> f, void *arg ) { std::cout << "bridge_set_pound_var_func is called " << std::endl ; return 0; }
};
typedef int (*funcPtr)(const char *, char *, void *) ;
typedef boost::function0<int&> boostBindFuncType;
class myC
{
public:
myA *myOA;
int func(const char * poundVar , char * t1, void * t2);
int myCCall()
{
std::cout << "myCCall is called " << std::endl;
myOA->bridge_set_pound_var_func( (boost::bind(&myC::func, this, _1, _2, _3)), (void *)this );
return 0;
}
};
int myC::func(const char * poundVar , char * t1, void * t2)
{
std::cout << "myC::func is called " << std::endl;
return 1;
}
int main()
{
myC myCO ;
myC *m1p = &myCO ;
m1p->myCCall() ;
return 0 ;
}
I cannot change the interface of bridge_set_pound_var_func, which is called by many other functions. Is is possible to transform boost::bind returned function object to a function pointer?
Traditionally the final void * argument passed to callbacks is user defined data. If this is the case for you you can create a helper function that will let you pass functors. the only trouble is that you need to ensure that the user data exists until the callback will no longer be called - and that will depend a lot on your program structure. I'm just going to leak the object as thats the easiest way to ensure it continues to exist. ( Though you'll also have problems with the existance of the containing myC object ).
class myC
{
public:
myA *myOA;
//NOTE: I've removed the void* ptr here, which should be user data.
// If you still need it you'll need to bind it away at functor creation time.
int func(const char * poundVar , char * t1);
int myCCall()
{
//TODO: Fix this intentional leak.
boost::function<int(const char*, char*)> * fn = new boost::function<int(const char*,char*)>( boost::bind(&myC::func,this) );
//Call our helper function instead of `set_pound_func`.
set_pound_func_with_functor(myOA, fn );
return;
}
};
// Function that is really passed to `set_pound_func` when
// set_pound_func_with_functor is called.
// It converts the user data back to a boost function and calls it.
int pound_func_with_functor(const char* d1, char* d2, void* user_data)
{
boost::function<int(const char*,char*)> * fn = static_cast< boost::function<int(const char*, char*) >( user_data );
return (*fn)(d1,d2);
}
//Helper function to make set_pound_func work with boost functions instead.
//NOTE: You are required to ensure the fn argument exists for long enough...
void set_pound_func_with_functor( myA * myOA, boost::function<int(const char *, char *)> & fn )
{
myOA->bridge_set_pound_var_func( &pound_func_with_functor, &fn );
}
There are no ways to convert boost::bind result to function pointer.
Use boost::function
int bridge_set_pound_var_func
( const boost::function<int(const char *, char *, void *)>& f, void *arg )
call as
myOA->bridge_set_pound_var_func( (boost::bind(&myC::func, this, _1, _2, _3)),
(void *)this );
or use template parameter
template<typename Func>
int bridge_set_pound_var_func( const Func& f, void *arg )
call as in first case.
You cannot convert result of boost::bind or boost::function to function-pointer.
I think read this will be interestring.
demote boost::function to a plain function pointer
In your case - you cannot use target, so, look at answer of Ian
The only thing you can pass as a function pointer is a function. No function objects, no lambdas, no nothing. Just global functions.

transfer a function as a parameter to a different function

I am trying to transfer a function as a parameter to a different function.
for some reason it is not working.
//myClass.h
class MyClass
{
public:
typedef int (*MyClass::ptrToMember)(float, char);
ptrToMember p1;
MyClass::MyClass();
void hello(ptrToMember fun);
int SendIt (float a, char b);
};
//MyClass.cpp
MyClass::MyClass(){
p1 = &(MyClass::SendIt);
hello(p1);
}
int MyClass::SendIt (float a, char b)
{
std::cout << "MyClass::SendIt "<<a<<std::endl;
return 1;
}
void MyClass::hello(ptrToMember fun){
int result = (*fun)(12, 'a');
std::cout << result << std::endl;
}
would appreciate it, if someone can tell me what my mistake is.
typedef int (*MyClass::ptrToMember)(float, char);
^
// your mistake is here
Pointers to class member functions are declared like this:
typedef int (MyClass::*ptrToMember)(float, char);
^
And called like this (test is the class instance - can also be 'this'):
(test.*pointer)(parameters) // if test is automatically allocated
or
(test->*pointer)(parameters) // if test is a pointer
The decleration operator is ::*, while the operator to invoke your pointer to a member function are .* and ->*.
Edit:
This line:
p1 = &(MyClass::SendIt);
actually has to be:
p1 = &MyClass::SendIt; // without parentheses
Say this:
typedef int (MyClass::*ptrToMember)(float, char);
// ...
int result = (this->*fun)(12, 'a');

The best and safety way to pass in extern function as a parameter a function of class without boost?

I've the following code:
#include <iostream>
typedef void ( *FuncPtr )( int );
extern void MyFunc( FuncPtr callback )
class MyClass
{
public:
void SomeFunction( int n )
{
std::cout << "bla: " << n << std::endl;
}
};
int main()
{
MyClass obj;
MyFunc( /* */ );
}
What is the best and safety way to pass in MyFunc function as a parameter a function of class without (SomeFunction) boost?
You can't, and even if your compiler allows it, I'm sure you'd get into undefined behavior.
SomeFunction is not like a free function, it is a member function. That means it operates on an object, so calling it outside of context is a sure path to disaster.
The idiom for C callbacks is to include user data which passes an arbitrary parameter through the function and back into the callback:
typedef void ( *FuncPtr )( int, uintptr_t user_data );
extern void MyFunc( FuncPtr callback, uintptr_t user_data );
When invoking a method on a class with a callback you use the user_data to pass the this pointer:
class MyClass
{
public:
void SomeFunction( int n )
{
std::cout << "bla: " << n << std::endl;
}
private:
static void SomeFunctionEntry( int n, uintptr_t user_data)
{
MyClass *ths = (MyClass *) user_data;
ths->SomeFunction(n);
}
};
The static function SomeFunctionEntry is a free function which can be invoked as a callback. You ensure its user_data argument is a valid class instance:
int main()
{
MyClass obj;
MyFunc(&MyClass::SomeFunctionEntry, (uintptr_t) &obj);
}
(side note: it is a very bad idea to pass an automatic variable like obj as a callback in a multithreaded environment because it is difficult to be sure that the pointer will still be valid when the callback is eventually invoked)