13

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)

3 Answers 3

6

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().

Sign up to request clarification or add additional context in comments.

4 Comments

+1: This is the standard workaround for this problem. Usually, your callbacks can receive a void * as parameter, to pass along context. This FAQ explains it in more detail.
However, this skips over the problem of globalLambdaFunctor's type, which isn't easily solved, since bind() returns something that depends on its arguments. And, of course, global variables come with a whole stack of problems...
Yes, well not very upliftin: the "Solution" in line 101
if you like I've come up with a solution that involves a little less typing and less error-prone.
4

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.

6 Comments

I cannot change the struct or PFUNCPLUGINCMD it's directly from Notepad++ Plugin Interface, and thus I cannot add the extra parameter either. I tried to do this with templates, but I cannot assign non-template types runtime.
@Ciantic: If you can't change that, and if Notepad++' plugin API indeed sports user callbacks without user parameters, then all you can do is to store the result of bind() in a global variable (possibly of the type function<void()>) and write a wrapper function which invokes that.
@sbi: Okay, I believe ya. But hold on as I get the code online, this is most retarded way to do this. Is this fixed in C++0x with anonymous functions: pFunc = []() { func(statement); }?
@Ciantic: It would be, if it weren't for the fact that the compiler will turn lambda functions into function objects... Really, if you need to have certain data passed to some callback someone else calls, I know of three possible ways (in decreasing preference): 1) using a function object, 2) passing a void* userdata around, and 3) a global variable. Somewhere that data has to be kept, and if you don't have anything attached to the callable entity (function object), and the function that calls the callback won't pass on any state to it, then there's only global data, as bad as that might be.
@sbi: I did it with global funcs @ GitHub, not very neat.
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.