Re: [C++-sig] [Implementation] Calling wrapped functions, converters, policies

David Abrahams <[email protected]>
Newsgroups gmane.comp.lib.boost.langbinding
Message-ID <[email protected]>
Daniel Wallin <[email protected]> writes:

> Sounds good. I actually wrote something like this yesterday morning, except
> I used the ConverterGenerator type instead of a nested type and I didn't
> think about passing the entire state tuple to the converters.
>
>    typename context_type<Policies>::type context(policies);
>
>    typedef typename find_converter_generator<Policies, 1>::type c1_gt;
>    typename c1_gt::template apply<T0, xxx_to_cpp>::type c1;
>
>    typedef typename find_converter_generator<Policies, 2>::type c2_gt;
>    typename c2_gt::template apply<T1, xxx_to_cpp>::type c2;
>
>    context.precall(params);
>
>    c1.convert(params[0], context.get((c1_gt*)0));
>    c2.convert(params[1], context.get((c2_gt*)0));
>                          ^^^^^^^^^^^^^^^^^
>    context.postcall(params);

I've been thinking of something a little bit different.  See below.

> Anyway, this seems great. Perhaps the requirements on
> ConverterGenerators/CallPolicies
> can be quite loose too;
>
>    May or may not contain a 'state' typedef.
>        - has_xxx
>
>    The state typedef may or may not be a mpl sequence.
>        - is_sequence

Bad idea, IMO.  Not all compilers support has_xxx, defaults
(e.g. typedef mpl::vector0 state) are easy to come by through
inheritance, and every metafunction invocation has a cost in compile
time.  I'd rather just establish a simple set of requirements.


Now, I know you've been thinking about things from the level of
policy composition by putting together things like 

       adopt(_1,_2) + release(_4)

or whatever syntax it is that you use.  I support using that sort of
construct, but I want to look at things from the low-level
implementation perspective of the invocation of the wrapped entity for
a moment.

One thing I discovered in trying to wrap factory functions as
constructors is that converters need access to the whole incoming
argument list, because the converter for parameter N of the called
function really needs to operate on parameter N+1 of the input (the
initial "self" argument is dropped).  I believe this is also the way
per-argument (or rather, per-converter) precall actions should be
handled - converters can just do the precall action in their convert()
functions.  The only capability lost from the current precall protocol
is the ability to fail overload resolution at that point, but I've
only ever used precall for one thing, and it never needed to fail
overload resolution so I don't believe it's important.

I'd like to see a templated protocol to access the actual
argument list, e.g.:

     get<1>(args)  ->  "argument 1"

we'd define a get<> which operates on PyObject* (argument tuples) but
we could also wrap the argument tuple in a kind of mapping to drop the
first argument (or inject a faux argument, in the case of an out
parameter which doesn't actually appear in the incoming argument
list).  For handling lone conversions (like extract<T>(obj)) we could
wrap a single PyObject* (argument) in a class for which only get<0>(x)
(but not get<1>, get<2>,...) was defined.

There may yet be reasons to include in the argument package the
ability to access a keyword dictionary.

So at the lowest level, we have:

   - an invocable entity (a function pointer/reference, function
     object, member function pointer, or possibly data member
     pointer, for getters/setters)

   - a tuple of argument/result converters

   - a shared, per-call state object

   - an argument package.

   - as a matter of implementation detail, for dispatching to the
     right calling overload, I believe we'll need:
   
        - a tag which describes how to do the invocation (function
          call syntax, member function syntax, data member
          access/assignment)

        - a tag which says whether the invocable entity's return type
          is void
       
        - a tag which describes the arity of the tuple of converters

     These can probably be combined into a single integral constant
     wrapper for efficiency.

Above that level, we need:

   - a way to deduce the signature of some callable objects like
     function pointers

   - a way to combine the signature of the callable object (either
     deduced or supplied explicitly) with the CallPolicies to produce
     the tuple type of argument/result converters

   - a way to combine the CallPolicies with the ArgumentPackage to
     produce a shared, per-call state type/object

   - a way to initialize an object of the arg/result converter tuple
     type with the shared, per-call state object and argument package
     (or we could combine the argument package into the shared,
     per-call state).

At the top level, we need:

   - A way to get the ArgumentPackage from the actual arguments passed.


Anything I'm missing?  Your thoughts?
     
-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.