开发者

How can I cast or convert boost bind to C function pointer?

开发者 https://www.devze.com 2023-03-05 14:46 出处:网络
Suppose I have this: void func(WCHAR* pythonStatement) { // Do something with pythonStatement } And I need to convert it to void function(void) like this:

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.


Ende开发者_高级运维d up using the wrapping "solution" (GitHub)


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.


You can't do this, unless you want to write your own Just-In-Time compiler. Alternatively, if you control the receiving code, then you could use a boost::function<>, which will accept a variety of function types, including pointers and function objects like those produced by boost::bind.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号