std::bind to c-style function pointer

Feb 13, 2013 at 10:09pm
Let's say I have to pass a function pointer to a library, and the library will call that function with no parameters. I got the impression hat std::bind allows me to bind a parameter to the function giving me an address that I can pass to the library so that then the function is called by the library with 0 parameters, on my end it is called with the parameters I want.

Somehow I don't think this is true, but I just wanted to check - is this true?
Last edited on Feb 13, 2013 at 10:38pm
Feb 13, 2013 at 10:10pm
AFAIK it works in reverse. You give bind some parameters to "bind" so that when you call it later those parameters are interested inserted for you.

If you want to do it the other way, couldn't you just make a wrapper function that takes no arguments and calls the other one with the args you want?
Last edited on Feb 13, 2013 at 10:14pm
Feb 13, 2013 at 10:12pm
I can't just make arbitrary wrapper functions at runtime ;p
Feb 13, 2013 at 10:14pm
Er wait I think I just contradicted myself...

Yes, bind does it the way you want. You would just bind all the parameters to the function, then you can call it with no arguments. If you want different parameters, just rebind them.
Feb 13, 2013 at 10:19pm
Can I do this?
1
2
3
4
5
6
7
8
9
void f(char const*str)
{
    std::cout << str << std::endl;
}

//...

LibraryObj1.add(static_cast<void (*)()>(std::bind(f, "A")));
LibraryObj2.add(static_cast<void (*)()>(std::bind(f, "B")));
Or would LibraryObj1 pass "B" when calling f?

EDIT: Looks like it can't: http://ideone.com/I5bMyB

Disappointing...
Last edited on Feb 13, 2013 at 10:28pm
Feb 13, 2013 at 10:29pm
Each invocation of bind creates a new function wrapper basically. So they would be separate, yes.
Last edited on Feb 13, 2013 at 10:29pm
Feb 13, 2013 at 10:31pm
I can't get them to be converted to c-style function pointers, though, so it is not useful for what I want to do :(

Any alternatives?

EDIT: I guess my question is how to do the impossible - I've done some reading and I understand how to do what I want to do.
Last edited on Feb 13, 2013 at 10:41pm
Feb 13, 2013 at 10:43pm
You could make the library take std::function objects instead of C function pointers. :P

I can't see another way around this because when you bind the function you have to store the data that is bound somewhere (part of a class or whatever), but a C pointer doesn't let you do that since it just points to some code (basically).
Feb 13, 2013 at 10:54pm
C style callbacks almost always take a "userdata" parameter so that problems like this can be addressed.

That is, something like this is typical:

1
2
3
4
5
6
7
8
void mycallback(void* userdata)
{
  //...
}

//...

func_that_takes_a_callback( mycallback, &foo );


Here, &foo would be passed as 'userdata' when the callback is called.


Using that, you can simply wrap the functor in a C-style callback function and use the userdata value to hold the functor object:

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef std::function<void()> callback_t;

void c_callback_wrapper( void* userdata )
{
  auto& callback = *reinterpret_cast<callback_t*>(userdata);
  callback();
}

//...

callback_t foo = std::bind( ... );

func_that_takes_a_callback( c_callback_wrapper, &foo );


A problem with this approach (and C style callbacks in general), is that the callback functor (in this case foo) must not go out of scope or be destroyed while there is still possibility of it being called.
Last edited on Feb 13, 2013 at 10:55pm
Feb 14, 2013 at 2:34am
@Disch yes I know and am aware of that, however there are situations where the library was poorly designed. Still though, it will help people who find this thread via google.
Feb 14, 2013 at 3:12am
I have yet to see a respectable/usable library that does not offer a userdata pointer for its callbacks. I would be very curious to know what lib you're using that doesn't have that functionality.
Feb 14, 2013 at 3:48am
Actually my problem wasn't with a library that didn't have a way to give custom user data - I was just trying to see if I could take some arbitrary std::function and get a c-style function pointer from it. I was wanting to do some magic where I used member functions of a class as my callbacks, but the issue is that the way the this pointer gets passed is implementation defined and I didn't want to relay on that. I've settled on forwarding since it works for what I need.
Feb 14, 2013 at 4:18am
closed account (S6k9GNh0)
Boost Asio does not use a "user data pointer" for its callbacks. It expects you to use std::bind or handle it some other way.
Feb 14, 2013 at 5:55am
@ computerquip: I said "C style" callbacks - where C++ functors are not an option.

obviously there's no need for them if you're using std::function.
Topic archived. No new replies allowed.