[C++-sig] Py++ wrapper generation and docstrings

Roman Yakovenko roman.yakovenko at gmail.com
Sun Sep 3 20:14:27 CEST 2006


On 9/3/06, Ganssauge, Gottfried <Gottfried.Ganssauge at haufe.de> wrote:
> > >      Now suppose the following:
> > >          type char array_t [7];
> > >
> > >            int search2 (void *instance, callback_t cb,
> > array_t *result);
> >
> > If you already create a wrapper, you can create  "better" wrapper:
> >
> > boost::python::tuple search2( void* instance, callback_t cb ){
> >     ...
> >     return boost::python::make_tuple( .... )
> > }
> That's what I'd like to achieve - but automatically!

Lets be more productive. Can you create small example, that you want to export
and Py++ script and I will make it work?

> >
> > >      How would both our generators interact with each other?
> >
> > I don't see the whole picture, so I can not answer your question.
> > I assume that you have some functions that take pointer to
> > callback, right?
> > You can not expose these functions as is, so you have to
> > write a wrapper for
> > them. Basically you should exclude the function from being exported,
> > and then you
> > should add your declaration and registration code. Next link should
> > help you with
> > your task:
> >
> >
> http://www.language-binding.net/pyplusplus/documentation/inserting_code.
> html
> >
> >
> > >      Finally I'm not sure about when to run my generator.
> >
> > In your case you may consider to run it twice:
> >
> > 1. first time you can generate your own header file. This file will
> > contain all wrappers.
> > 2. second time you weel feed just generated header fileand original
> > sources to Py++.
> >
> That was my first attempt, but it became difficult to chain several
> generators together.
> Eventually I should really consider doing several generator passes to a
> temp file until the temp file doesn't change anymore.
> This could take quite some time because gccxml must parse the
> intermediate files...
> Furthermore I'm not yet sure how to forward the original function names
> ...

I still fill that I don't have enough information to help you. For the
last problem I
can give you small hint: mangle generated function name.

Take a look on boost_random example:
http://tinyurl.com/gwc2t
http://tinyurl.com/kocap

I introduced small convention about struct names and than I reused this
information from the script.


> >
> > >       I got another generator which generates wrappers for functions
> > > expecting "const unsigned char *" arguments for strings ...
> > >
> > > 2.) docstring extraction is not really usable at the moment
> > >     consider the attached test case
> > >        [test1.hpp, pypp_test1.py]
> > >
> > >     When using the "latin1_doc_string" doc_extractor some unicode
> > > exception is thrown.
> >
> > I will take a look on this. I did not thought about unicodes :-(. It
> > will take some time to
> > convert Py++ to support it. I think, that doc_extractor will change,
> > because you will
> > have to provide encoding. Otherwise, I will not be able to
> > write code to files.
> This could be a property on the doc_extractor.

Yes I know, that is exactly what I meant by "doc_extractor" will change.

> Currently I'm using
>     string_escapes = re.compile (r'((\\x[a-f0-9][a-f0-9])|(\\*"))',
> re.I)
>     def make_cstring (s):
>         def replace_escape(m):
>             g = m.group(1)
>             if g.startswith ('\\x'):
>                 return g + '""'
>             elif g == '"':
>                 return '\\"'
>             else:
>                 return g
>
>         return '"%s"' % hex_escape.sub (replace_escape, repr (s) [1:-1])
>
> This copes with the problem of hex escapes followed by valid hex
> characters and with embedded quotes.

May I copy this code to Py++ contrib package under the license(
http://www.boost.org/more/license_info.html )

> > It seems that you found work around to "pointer to function" problem.
> > Can you create
> > small example with explanation how it should be done. May be I will
> > able to introduce
> > this functionality to Py++.
> Well not for any case.
> Function pointers without instance pointers still can't be exposed for
> the reasons given in the reference provided by Py++.
> Function pointers _with_ instance pointers are a different kind of
> beast.
> Generally function declarations using this type of callback have exactly
> one function pointer argument and exactly one void *argument which is
> forwarded to the callback function.
>         typedef callback_return_type (*callback_t) (callback_args, void
> *instance, more callback_args);
>
>         return_type function (args ..., callback_t, more args, void
> *instance, more args)
>
> Functions having this kind of signature may be wrapped like this:
>
>         callback_return_type wrap_callback_t (callback_args, void
> *instance, more callback_args) {
>                 PyObject *py_instance = reinterpret_cast<PyObject *>
> (instance);
>
>                 if (py_instance) {
>                         try {
>                                 return
> (boost::python::call<callback_return_type> (py_instance, callback_args,
> more callback_args))
>                         }
>
>                         except (...) {
>                         }
>                 }
>
>                 return some error value;
>         }
>
>         return_type function_wrapper (PyObject *instance, args,
> more_args, ...) {
>                 return (function (args ..., &wrap_callback_t, more args,
> instance, more args));
>         }
>
> I'm attaching the generators module I'm currently using ...
> The generators are called like this:
>     def wrap_functions (self, decls):
>         """
>         Generate wrappers for functions otherwise not exportable in
> their
>         current_form
>
>         @param decls
>         Function declarations to be wrapped
>         """
>         wrapper_generators = [
>             callback_wrapper_generator (self),
>             const_byte_wrapper_generator (self)
>         ]
>         finished = False
>         while not finished:
>             finished = True
>             for d in decls:
>                 for g in wrapper_generators:
>                     cookie = g.applies (d)
>                     if cookie:
>                         g (cookie)
>                         finished = False
>                         break
>

Thank you for explanation.

May I copy this code to Py++ contrib package under the license(
http://www.boost.org/more/license_info.html )


-- 
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/



More information about the Cplusplus-sig mailing list