Suppose I have this:
void func(WCHAR* pythonStatement) {
// Do something with pythonStatement
}
And I need to convert it to void function(void) like this:
bind(func, TEXT("console.write('test')"))
Now I have struct like this:
typedef void (__cdecl * PFUNCPLUGINCMD)();
struct FuncItem {
PFUNCPLUGINCMD pFunc;
// ...
};
How can I set the pFunc of my struct to bind(func, "something")
? Bind returns lambda_functor not a function pointer, so how can I cast this functor to function pointer?
Thanks.
Ended up using the wrapping "solution" (GitHub)
Yes, it can. This is purpose of casting function pointers, just like usual pointers. We can cast a function pointer to another function pointer type but cannot call a function using casted pointer if the function pointer is not compatible with the function to be called.
boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. It supports arbitrary function objects, functions, function pointers, and member function pointers, and is able to bind any argument to a specific value or route input arguments into arbitrary positions.
I think that you can't, unless you make the resulting lamba_functor a global variable.
In that case, you could declare a function that invokes it:
void uglyWorkaround() {
globalLambdaFunctor();
}
and set pFunc
to uglyWorkaround()
.
EDIT
Just a sidenote: if you are binding static text to the function call, you may completely omit bind()
call and write just:
void wrapper() {
func(TEXT("console.write('test')"));
}
and set pFunc
to wrapper()
.
Bind returns lambda_functor not a function pointer, so how can I cast this functor to function pointer?
I don't think you can. However, off the top of my head, I can think of several alternatives:
Use boost::function<void()>
(or std::function()
if your compiler supports TR1 or C++11) instead of void (*)()
.
It has the ability to bind to just about anything with a somewhat compatible signature.
Put the whole code into a template, make PFUNCPLUGINCMD
a template parameter, and let function template argument deduction figure out the exact type.
That's a variation on the former, actually, where you would use the result of bind()
directly instead of having boost::function
abstract away the gory details.
Create a wrapper that calls the functor returned by boost::bind()
.
A function template might help to let the compiler figure out the exact types and generate a suitable function, although I haven't tried to do that. However, since you cannot use the result of bind()
as a template argument, but need to have give the function access to it nevertheless, you will need a global variable for this. (The ability to avoid this is one of the main advantages of function objects, a very versatile of which is std::function
.)
Extend your PFUNCPLUGINCMD
callback type to support a user-provided parameter. For C callbacks, this usually is a void*
. However, if you pass the address of the object returned by bind()
to your callback, you would need to convert it into a pointer to the correct type - which, AFAIK, depends on the arguments provided to bind()
. In order to avoid that, you'd need to pass something that abstracts away the exact type. Again, std::function
comes to the rescue.
The first idea would be the best, but it requires you to be able to change PFUNCPLUGINCMD
. The last one might be best when PFUNCPLUGINCMD
needs to be compatible with C, as it uses the common C callback idiom.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With