[Bind & Function] c function pointers
Hello all, It was pointed out to me that the subject line was not correct, so I resent this mail with a correct subject line. I'm not sure if this is possible at all, but let me explain: I have the following function signature: typedef int (*sasl_callback_ft)(void); That function in question gets called with unknown amount of parameters (usually 3 or 4) Now I want to assign a member function to it: class admin { public: int callback_fun(void *context, int id, const char **result, unsigned *len); } boost::function<int(void *, int, const char **, unsigned *)> callback = boost::bind(&admin::callback_fun, this, _1, _2, _3, _4); Obviously the compiler doesn't allow to assign callback to a sasl_callback_ft var sasl_callback_ft fun = callback; I get compiler errors like: matthijs@hammer:~/t2$ clang++ -o main -std=c++11 main.cpp main.cpp:22:19: error: no viable conversion from 'boost::function<int (void *, int, const char **, unsigned int *)>' to 'sasl_callback_ft' (aka 'int (*)()') sasl_callback_ft cbfun = cb; ^ ~~ /usr/include/boost/function/function_template.hpp:894:5: note: candidate function operator safe_bool () const ^ 1 error generated. Attached the testcase I made for this. Regards, Matthijs
On Fri, Nov 29, 2013 at 11:23:35AM +0100, Matthijs Möhlmann wrote:
Hello all, I'm not sure if this is possible at all, but let me explain:
It's not possible.
I have the following function signature: typedef int (*sasl_callback_ft)(void);
That function in question gets called with unknown amount of parameters (usually 3 or 4)
That doesn't quite make sense. That signature is for a function that takes exactly zero arguments, both in C and C++.
boost::function<int(void *, int, const char **, unsigned *)> callback = boost::bind(&admin::callback_fun, this, _1, _2, _3, _4);
Obviously the compiler doesn't allow to assign callback to a sasl_callback_ft var sasl_callback_ft fun = callback;
Both boost::function and the return type of boost::bind are objects of a Callable type. They bear no relation to traditional function pointers except that you can call them with the same kind of syntax. A function pointer can be assigned a free function, a static member function or a stateless lambda. You may want to look into libraries that via code generation or other tricks produce a completely new function in memory, often called a "thunk" or a "trampoline", which forwards to the actual more complex callable. Another approach is to store state in some external/global/thread-local storage and assign a free function that forwards the call based on the stored state and any other state you can gleam from your library. Often, C-like APIs like the one you try to interact with tends to have a void* in the interface which you can use to tunnel the information needed to call the right thing. If this API doesn't have such a thing, you're in for a fun time. -- Lars Viklund | zao@acc.umu.se
On 11/29/13, 1:37 PM, Lars Viklund wrote:
On Fri, Nov 29, 2013 at 11:23:35AM +0100, Matthijs Möhlmann wrote:
Hello all, I'm not sure if this is possible at all, but let me explain: It's not possible.
Ok, thank you.
I have the following function signature: typedef int (*sasl_callback_ft)(void);
That function in question gets called with unknown amount of parameters (usually 3 or 4) That doesn't quite make sense. That signature is for a function that takes exactly zero arguments, both in C and C++. That's strange, the SASL library uses that as Signature and I can assign a function with 3/4 arguments to that. boost::function<int(void *, int, const char **, unsigned *)> callback = boost::bind(&admin::callback_fun, this, _1, _2, _3, _4);
Obviously the compiler doesn't allow to assign callback to a sasl_callback_ft var sasl_callback_ft fun = callback; Both boost::function and the return type of boost::bind are objects of a Callable type. They bear no relation to traditional function pointers except that you can call them with the same kind of syntax.
A function pointer can be assigned a free function, a static member function or a stateless lambda.
You may want to look into libraries that via code generation or other tricks produce a completely new function in memory, often called a "thunk" or a "trampoline", which forwards to the actual more complex callable.
Another approach is to store state in some external/global/thread-local storage and assign a free function that forwards the call based on the stored state and any other state you can gleam from your library.
Often, C-like APIs like the one you try to interact with tends to have a void* in the interface which you can use to tunnel the information needed to call the right thing. If this API doesn't have such a thing, you're in for a fun time.
Thank you for the suggestions, I'm going to look at that. Regards, Matthijs
participants (2)
-
Lars Viklund
-
Matthijs Möhlmann