Determining interest in Delegates submission

I would like to determine interest in a possible library submission. I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has some limitations which I will describe shortly. The basic idea is to be able to convert: R (B::*)(T0,T1,…) and B* to R (*)(T0,T1,…) Here's an example usage: class foo { int x; int test(int v) {return x + v;} }; foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7" When I first attempted this I used a technique where I allocated some executable memory in the heap and dynamically created a free function to call the member function for the instance. It was fun attempting that but, as you can imagine, as soon as I used the optimizer flags on my compiler I would get segment faults :) My second approach was to use templates and the Boost Preprocessor library to create appropriate static arrays of pointers to free functions matching the required signatures and then hand those pointers out each time the delegate() function is called. The two downsides to this are: you can only call delegate() for a certain function signature a limited number of times, and it adds a lot of potentially unused code to your executable. Here's the code (I've stripped out error checking for the sake of illustration): #include <boost/preprocessor.hpp> #ifndef _delegate_h_ #define _delegate_h_ #define MAX_DELEGATES 256 #define DELEGATE_PARAMS 0 #include "delegate_template.hpp" #undef DELEGATE_PARAMS #define DELEGATE_PARAMS 1 #include "delegate_template.hpp" #undef DELEGATE_PARAMS // … #endif // delegate_template.hpp #define DELEGATE_STORE BOOST_PP_CAT(DELEGATE_STORE,**DELEGATE_PARAMS) template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > struct DELEGATE_STORE { typedef B* objectPointer; typedef R (B::*memberFunction)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ); typedef R (*freeFunction)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ); static int delegateCount; static int delegateMax; static objectPointer delegateObjectPointer[MAX_**DELEGATES]; static memberFunction delegateMemberFunction[MAX_**DELEGATES]; template <int i> static R func( BOOST_PP_ENUM_BINARY_PARAMS(**DELEGATE_PARAMS, T, v) ) { return (delegateObjectPointer[i]->***delegateMemberFunction[i])( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, v) ); } static const freeFunction delegateFreeFunction[MAX_**DELEGATES]; static freeFunction getDelegate(objectPointer o, memberFunction m) { int delegateIndex = delegateCount++; delegateObjectPointer[**delegateIndex] = o; delegateMemberFunction[**delegateIndex] = m; return delegateFreeFunction[**delegateIndex]; } }; template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > int DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateCount = 0;
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > int DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateMax = MAX_DELEGATES;
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::memberFunction DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateMemberFunction[MAX_**DELEGATES] = {0};
template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::objectPointer DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateObjectPointer[MAX_**DELEGATES] = {0};
#define FUNC_POINTER(z, n, params) &DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::template func< n >, template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > const typename DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::freeFunction DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T)
::delegateFreeFunction[MAX_**DELEGATES] = {
BOOST_PP_REPEAT(MAX_DELEGATES, FUNC_POINTER,) }; template <class B, class R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, class T) > R (*delegate( B* b, R (B::*f)( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ) ))( BOOST_PP_ENUM_PARAMS(DELEGATE_**PARAMS, T) ) { return DELEGATE_STORE<B,R BOOST_PP_ENUM_TRAILING_PARAMS(**DELEGATE_PARAMS, T) >::getDelegate(b, f); } // end Thankyou very much if you managed to read all the way to here! By the way, this is my first active participation in any open source project :) Jared

On Wed, Sep 7, 2011 at 7:48 PM, Jared McKee <jared.mckee@gmail.com> wrote:
I would like to determine interest in a possible library submission.
I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has some limitations which I will describe shortly.
The basic idea is to be able to convert:
R (B::*)(T0,T1,…) and B*
to
R (*)(T0,T1,…)
Here's an example usage:
class foo { int x; int test(int v) {return x + v;} };
foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7"
[...snip implementation notes...] I admit I only glossed over your implementation notes, but it looks like this would be very similar to (or...the same as...?) a bound (e.g., via Boost.Bind) boost::mem_fn: http://www.boost.org/doc/libs/1_47_0/libs/bind/mem_fn.html Is that accurate? By the way, this is my first active participation in any open source project
:)
Jared
Welcome! - Jeff

On Thu, Sep 8, 2011 at 10:19 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Wed, Sep 7, 2011 at 7:48 PM, Jared McKee <jared.mckee@gmail.com> wrote:
I would like to determine interest in a possible library submission.
I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has some limitations which I will describe shortly.
The basic idea is to be able to convert:
R (B::*)(T0,T1,…) and B*
to
R (*)(T0,T1,…)
Here's an example usage:
class foo { int x; int test(int v) {return x + v;} };
foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7"
[...snip implementation notes...]
I admit I only glossed over your implementation notes, but it looks like this would be very similar to (or...the same as...?) a bound (e.g., via Boost.Bind) boost::mem_fn:
http://www.boost.org/doc/libs/1_47_0/libs/bind/mem_fn.html
Is that accurate?
Good question. I believe the approach in boost::mem_fn is to create C++ functor objects which are structs with operator() overloaded. These functors are not compatible with straight C function pointers. My implementation returns C function pointers, not functors. Here's a discussion about the topic: http://stackoverflow.com/questions/1840029/passing-functor-as-function-point...
By the way, this is my first active participation in any open source project
:)
Jared
Welcome!
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thu, Sep 8, 2011 at 7:46 AM, Jared McKee <jared.mckee@gmail.com> wrote:
On Thu, Sep 8, 2011 at 10:19 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Wed, Sep 7, 2011 at 7:48 PM, Jared McKee <jared.mckee@gmail.com>
wrote:
I would like to determine interest in a possible library submission.
I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has
some
limitations which I will describe shortly.
The basic idea is to be able to convert:
R (B::*)(T0,T1,…) and B*
to
R (*)(T0,T1,…)
Here's an example usage:
class foo { int x; int test(int v) {return x + v;} };
foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7"
[...snip implementation notes...]
I admit I only glossed over your implementation notes, but it looks like this would be very similar to (or...the same as...?) a bound (e.g., via Boost.Bind) boost::mem_fn:
http://www.boost.org/doc/libs/1_47_0/libs/bind/mem_fn.html
Is that accurate?
Good question. I believe the approach in boost::mem_fn is to create C++ functor objects which are structs with operator() overloaded. These functors are not compatible with straight C function pointers. My implementation returns C function pointers, not functors.
Here's a discussion about the topic:
http://stackoverflow.com/questions/1840029/passing-functor-as-function-point...
Oh...dear. I can see the use for a small module that converts C++ functors into a kind of (function pointer, void*) struct for use with interfacing with C-style APIs, but trying to get a lonely function pointer to call a functor seems wrought with peril (e.g., "gotchas" and safety issues)... I assume you're trying to provide a general solution to the 3rd case within the first answer to the referenced stackoverflow link? - Jeff

On Thu, Sep 8, 2011 at 11:29 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Thu, Sep 8, 2011 at 7:46 AM, Jared McKee <jared.mckee@gmail.com> wrote:
On Thu, Sep 8, 2011 at 10:19 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Wed, Sep 7, 2011 at 7:48 PM, Jared McKee <jared.mckee@gmail.com>
wrote:
I would like to determine interest in a possible library submission.
I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has
some
limitations which I will describe shortly.
The basic idea is to be able to convert:
R (B::*)(T0,T1,…) and B*
to
R (*)(T0,T1,…)
Here's an example usage:
class foo { int x; int test(int v) {return x + v;} };
foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7"
[...snip implementation notes...]
I admit I only glossed over your implementation notes, but it looks like this would be very similar to (or...the same as...?) a bound (e.g., via Boost.Bind) boost::mem_fn:
http://www.boost.org/doc/libs/1_47_0/libs/bind/mem_fn.html
Is that accurate?
Good question. I believe the approach in boost::mem_fn is to create C++ functor objects which are structs with operator() overloaded. These functors are not compatible with straight C function pointers. My implementation returns C function pointers, not functors.
Here's a discussion about the topic:
http://stackoverflow.com/questions/1840029/passing-functor-as-function-point...
Oh...dear.
I can see the use for a small module that converts C++ functors into a kind of (function pointer, void*) struct for use with interfacing with C-style APIs, but trying to get a lonely function pointer to call a functor seems wrought with peril (e.g., "gotchas" and safety issues)... I assume you're trying to provide a general solution to the 3rd case within the first answer to the referenced stackoverflow link?
That's exactly right.
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Thu, Sep 8, 2011 at 11:48 AM, Jared McKee <jared.mckee@gmail.com> wrote:
On Thu, Sep 8, 2011 at 11:29 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Thu, Sep 8, 2011 at 7:46 AM, Jared McKee <jared.mckee@gmail.com> wrote:
On Thu, Sep 8, 2011 at 10:19 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Wed, Sep 7, 2011 at 7:48 PM, Jared McKee <jared.mckee@gmail.com>
wrote:
I would like to determine interest in a possible library submission.
I have written some code which converts a member function and object pointer combination to a free function for use in C style callbacks. It has
some
limitations which I will describe shortly.
The basic idea is to be able to convert:
R (B::*)(T0,T1,…) and B*
to
R (*)(T0,T1,…)
Here's an example usage:
class foo { int x; int test(int v) {return x + v;} };
foo* a = new foo; a->x = 3; int (*f)(int) = delegate(a, &foo::inc); cout << f(4) << endl; // outputs "7"
[...snip implementation notes...]
Here's a discussion about the topic:
http://stackoverflow.com/questions/1840029/passing-functor-as-function-point...
Oh...dear.
From stackoverflow there is a link to http://fscked.org/proj/minihax/autocode/functorptr.cc, where the idea is you have a "mold" (I'd call it a template, but...) for the function signature you want to call like
static bool closure() { Functor *thisptr = (Functor *)MAX_INT; return (*thisptr)(); } And then allocate some memory, copy the executable code from that function mold (ie memcpy(newptr, closure, guess_at_size) and look through that memory, find MAX_INT and replace it with the runtime-obtained 'this' pointer. When I was crazy enough to consider this in the past, I used 0xAD0BEA1D instead of MAX_INT. (ie Adobe Aid, as the photoshop plugin callback spec uses function pointers without the ever-so-useful void * extraData param. Disclaimer: this was NOT when I worked at Adobe, but at a place where we were writing a paint package that supported PS plugins). I would just worry about MAX_INT being too common of a thing to find in bytes of executable. But maybe 0xAD0BEA1D is a valid instruction sequence on some platform. Anyhow.... Now I can _imagine_ doing the same thing, but templatized to get any function signature, but I can't say I'd recommend it. Not for a boost library. Or outside a boost library, for that matter. (I think in our case we eventually went with to thread-local storage, as we just needed a function pointer per thread.) Tony
participants (3)
-
Gottlob Frege
-
Jared McKee
-
Jeffrey Lee Hellrung, Jr.