Boost logo

Boost :

From: Thomas Wenisch (twenisch_at_[hidden])
Date: 2002-07-27 16:33:42


Hi all,

I was browsing through the new version of Boost.Function yesterday in CVS
and I was very impressed with the clever templates that can pick apart the
return value, arity, and argument types of a function type.

I am currently faced with the problem of interfacing to an "object
oriented C" framework that makes heavy use of function pointer callbacks,
where the typedefs for the function pointers are quite complex. In my C++
code, I have C++ objects that correspond to what the C framework expects,
and I have been writing trampoline functions to forward C callbacks to
appropriate C++ member functions. Writing the trampoline functions has
turned into a major hassle, since there are so many callback types to
support. The changes to Boost.Function inspired me to try to write a
trampoline template that will automatically generate trampoline functions
for me.

My requirement is the following. Given some C callback typedef, and an
"object" containing function pointers (untested code, apologies for
syntax problems):

/* Header file from the C framework. Hands off. */

struct c_style_object; /* Forward declare */

typedef struct return_type* (*callback_fn_t)(struct c_style_object
    *this, int arg1, float arg2);

typedef struct c_style_object {
  callback_fn_t callback;
  //... other callbacks & data members
} c_style_object_t;

And a corresponding C++ class implementing the specified interface:

//My code. Modify freely.

class CppStyleImplementation {
    //... Other stuff ...
  public:
    return_type * callback(int arg1, float arg2);
};

I want to be able to tie things together so that I get the callback from
the C framework to the correct C++ implementation function with the
minimum of pain.

My current thought is that the glue should work like this:

struct c_style_object_GlueClass {
   struct POD_glue {
      c_style_object_t c_style_iface;
      CppStyleImplementation *cpp_implementation;
   };

   static POD_glue * construct() {
      cpp_implementation = new CppStyleImplementation();
      c_style_iface.callback = & Trampoline<c_style_object_t,
          & CppStyleImplementation::callback>::trampoline;
   }
};

The glue class provides a POD struct so that when the C code calls the
trampoline with a c_style_object_t *, the trampoline can safely upcast to
POD_glue * and then access the cpp_implementation. Trampoline<> is a
magic template that somehow takes apart the C style typedef and the
provided member function pointer to the C++ function, and creates the
correct trampoline with a signature matching the typedef, or generates a
compile error if the supplied typedef and function cannot possible by
connected to each other (ie completely different arities, incovertible
paramter types, etc).

The GlueClass itself would ideally be a template that takes on as much of
the work of glueing the C and C++ together, for example, defining the
struct type.

The sytax above is all hypothetical, and I'm not married to any of it (ie
the templates may need more/different parameters or invocation syntax).

Here are my questions for the Boost community:

1) Can some combination of Boost.Function, Boost.Bind, etc already
accomplish what I need?

I haven't really made much use of these libraries beyond toy examples, so
I don't have a feel for what's already possible. No sense reinventing the
wheel if its already there.

2) Is this kind of template possible, or am I hopelessly doomed by
calling convention problems. In otherwords, can a C++ template generate a
function whose address I can pass to C code and expect it to work?

>From what I can tell, this is not an issue since the calling convention
of C and C++ is the same even if name linkage is different, and since I am
passing around addresses, I don't care what the name (for linkage
purposes) of the C++ function is. However, if I am wrong about this, then
I should stop wasting my time trying to implement it.

3) If the answer to 1 is no, and the answer to 2 is yes, would anyone
else out there benefit from a facility like this?

If the answer is yes, I will try to come up with a generic solution that
may be appropriate for Boost (ie follow style guidelines, etc). If no one
else needs it, I will save myself the trouble and just solve my immediate
problem.

4) Is there any chance the typedef "parsing" templates that are now in
Boost.Function could be extracted and moved into the Type Traits
library?

Also, it would be nice if there was one template that could figure out
arity, argument, and return types whether the construct passed to it is a
pointer-to-fn, reference-to-fn, fn-type, or the corresponding mem-fn
types. From my reading of it, the code in Boost.Function only works for
function types, and not pointers, references, or member functions.

Right now, I am copy-pasting the typedef parsing code out of
Boost.Function. It would make more sense to me if the facility where
publicly accessible in the Type Traits library. I don't feel comfortable
using something that lives in boost::function::detail directly.

Thanks for any feedback,
-Tom Wenisch
Computer Architecture Lab
Carnegie Mellon University


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk