[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