Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::bind for C function
From: Nick Jones (nick.jones_at_[hidden])
Date: 2012-12-20 23:14:15


On Friday, December 21, 2012 09:32 AM, Lars Viklund wrote:
> On Fri, Dec 21, 2012 at 12:30:20AM +0100, Philipp Kraus wrote:
>> Hello,
>>
>> I have got a a C library function call, which defines a function:
>> typedef int (*CFunction) (State* K);
>>
>> So I would like to use boost::bind / boost::function to create the binding
>> to a class method:
>>
>> boost::function<CFunction>( boost::bind(&MyClass::myMethod, this) )
>>
>> so that I can use the class method with the CFunction signature.
>> I would like to call a class method with the object context like a
>> C function.
>>
>> Can anybody help me to create a correct binding?
> Within the standard language, no, there is no way to get a free function
> pointer to an arbitrary callable.
>
> The result of a bind expression is not a free function pointer nor
> convertible to one. It's an object of an unspecified class type with a
> suitable operator ().
>
> You have several horrible choices for getting a free function pointer
> from something like this.
>
> Stateless C++11 lambdas can be coerced into a free function pointer, but
> as they're stateless, they will not fly here.
>
> The common within-the-language solution is to make a free "trampoline"
> function that forwards calls to your object, which it retrieves from
> some secret hiding place. In some APIs, you can pass in a "context" or
> "state" object at the same place you provide the free function pointer
> to the callback:
>
> R trampoline(State* s, A0 a0, A1 a1) {
> return get_my_callable(s)(a0, a1);
> }
>
> register_callback_with_api(&trampoline, &my_callable);
>
> Another choice that is not within the standard is to generate machine
> code for a trampoline-like function that directly forwards your call,
> either through some code generation library like Xbyak or by taking a
> suitable function, copying the generated code and patch the parts where
> the call happens.
>
> The above is often called "thunking".

If the State structure has a void *user_data field, then you can use the
following:

template<typename T, int (T::*method)(State *s, A0 a0, A1 a1)>
static int c_callable(State *s, A0 a0, A1 a1)
   {
   return (static_cast<T*>(s->user_data)->*method)(s, a0, a1);
   }

>
> In summary, the ways in order of unhorribleness are:
>
> 1) squirrel the actual callable away in some context/state provided to
> the trampoline;
>
> 2) squirrel the actual callable away in some global or static variable,
> which the trampoline uses;
>
> 3) dive into the abyss of code/thunk generation.
>

-- 
Nick Jones                              nick.jones_at_[hidden]
Senior Manager                          Core Development Team
Network Box Corporation Ltd
16th Floor, Metro Loft,
38 Kwai Hei Street,                     Tel: +852 2736 2083
Kwai Chung, Kowloon,                    Fax: +852 2736 2778
Hong Kong S.A.R.                        www.network-box.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net