pygccxml-development Mailing List for C++ Python language bindings (Page 21)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
| 2006 |
Jan
|
Feb
(6) |
Mar
(160) |
Apr
(96) |
May
(152) |
Jun
(72) |
Jul
(99) |
Aug
(189) |
Sep
(161) |
Oct
(110) |
Nov
(9) |
Dec
(3) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(13) |
Feb
(48) |
Mar
(35) |
Apr
(7) |
May
(37) |
Jun
(8) |
Jul
(15) |
Aug
(8) |
Sep
(2) |
Oct
(1) |
Nov
(2) |
Dec
(38) |
| 2008 |
Jan
(11) |
Feb
(29) |
Mar
(17) |
Apr
(3) |
May
|
Jun
(64) |
Jul
(49) |
Aug
(51) |
Sep
(18) |
Oct
(22) |
Nov
(9) |
Dec
(9) |
| 2009 |
Jan
(28) |
Feb
(15) |
Mar
(2) |
Apr
(11) |
May
(6) |
Jun
(2) |
Jul
(3) |
Aug
(34) |
Sep
(5) |
Oct
(7) |
Nov
(13) |
Dec
(14) |
| 2010 |
Jan
(39) |
Feb
(3) |
Mar
(3) |
Apr
(14) |
May
(11) |
Jun
(8) |
Jul
(9) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
(7) |
Apr
|
May
|
Jun
(3) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
| 2016 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2019 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2021 |
Jan
(1) |
Feb
(1) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(1) |
Nov
|
Dec
|
|
From: Kevin W. <kev...@gm...> - 2008-02-26 00:12:36
|
I'm new to Py++ but I've been experimenting with wrapping wxWidgets,
the cross platform GUI library.
It has gone fairly well, but I'm getting the following error and I'm
not sure how to resolve it.
In a header file somewhere, a global called "wxPanelNameStr" is declared:
extern WXDLLEXPORT_DATA(const char) wxPanelNameStr[];
The implementation is in a CPP file somewhere else:
extern WXDLLEXPORT_DATA(const char) wxPanelNameStr[] = "panel";
My problem arises in a constructor which uses wxPanelNameStr as the
default value for one of its arguments:
inline wxWindow(wxWindow *parent, wxWindowID winid,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxPanelNameStr)
Py++ generates the following code for this:
.def( bp::init< wxWindow *, wxWindowID, bp::optional< wxPoint
const &, wxSize const &, long int, wxString const & > >((
bp::arg("parent"), bp::arg("winid"), bp::arg("pos")=wxDefaultPosition,
bp::arg("size")=wxDefaultSize, bp::arg("style")=(long int)(0),
bp::arg("name")=wxPanelNameStr )) );
You'll note that the sixth argument takes a value of type const
wxString&, but the default argument in the generated code is const
char []. The error I get is long and does lots of complaining about
convertables and char[], but ultimately I think it boils down to this
line:
../boost_1_34_1/boost/python/type_id.hpp:88: error: invalid use of
array with unspecified bounds
wxString does have a constructor which takes const char*, so the
implicit conversion should happen, but I think Boost::Python is
getting confused.
Does anyone know how I can resolve this?
|
|
From: Gustavo C. <gjc...@gm...> - 2008-02-17 19:49:36
|
On 17/02/2008, Roman Yakovenko <rom...@gm...> wrote:
>
> On Feb 16, 2008 9:02 PM, Roman Yakovenko <rom...@gm...>
> wrote:
> >
> > On Feb 16, 2008 8:25 PM, Gustavo Carneiro <gjc...@gm...> wrote:
> > > Hi. I am looking at scanning with pygccxml a pure C header file, that
> looks
> > > like this:
> > >
> > > #ifndef __HELLO_H__
> > > #define __HELLO_H__
> > >
> > > #ifdef __cplusplus
> > > extern "C"
> > > {
> > > #endif
> > >
> > >
> > > void hello_print(const char *message);
> > > double hello_sum(double x, double y);
> > >
> > >
> > > #ifdef __cplusplus
> > > }
> > > #endif
> > >
> > > #endif /* __HELLO_H__ */
> > >
> > > My current code, that woks for C++ headers perfectly, fails with this
> pure C
> > > header file:
> > >
> > > File "../pybindgen/gccxmlparser.py", line 416, in parse_init
> > > self.module_namespace =
> > > declarations.get_global_namespace(self.declarations)
> > > File
> > >
> "/usr/local//lib/python2.5/site-packages/pygccxml/declarations/algorithm.py",
> > > line 170, in get_global_namespace
> > > raise RuntimeError( "Unable to find global namespace." )
> > > RuntimeError: Unable to find global namespace.
> > >
> > > Any tips on what I should be using instead of get_global_namespace()
> to get
> > > the definitions?
> > >
> >
> > Let me check this.
>
> Well I created tester and it is working fine. Can you take a look on
> "plain_c_tester.py" and modify it, so I can see the problem too.
"&"%$!
I screwed up big. There was a problem in my build script, and the list of
files that I gave pygccxml to scan was actually empty! :-/
Sorry for wasting your time. It works fine now.
I might only have a minor complaint in that pygccxml silently allows parsing
an empty list of header files, and in the end gives an error message that
does not appear very related to the error. Maybe pygccxml should raise
ValueError if I ask it to parse an empty list of header files?
Anyway, thanks a lot for looking into this.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
|
|
From: Roman Y. <rom...@gm...> - 2008-02-17 18:39:39
|
On Feb 16, 2008 9:02 PM, Roman Yakovenko <rom...@gm...> wrote:
>
> On Feb 16, 2008 8:25 PM, Gustavo Carneiro <gjc...@gm...> wrote:
> > Hi. I am looking at scanning with pygccxml a pure C header file, that looks
> > like this:
> >
> > #ifndef __HELLO_H__
> > #define __HELLO_H__
> >
> > #ifdef __cplusplus
> > extern "C"
> > {
> > #endif
> >
> >
> > void hello_print(const char *message);
> > double hello_sum(double x, double y);
> >
> >
> > #ifdef __cplusplus
> > }
> > #endif
> >
> > #endif /* __HELLO_H__ */
> >
> > My current code, that woks for C++ headers perfectly, fails with this pure C
> > header file:
> >
> > File "../pybindgen/gccxmlparser.py", line 416, in parse_init
> > self.module_namespace =
> > declarations.get_global_namespace(self.declarations)
> > File
> > "/usr/local//lib/python2.5/site-packages/pygccxml/declarations/algorithm.py",
> > line 170, in get_global_namespace
> > raise RuntimeError( "Unable to find global namespace." )
> > RuntimeError: Unable to find global namespace.
> >
> > Any tips on what I should be using instead of get_global_namespace() to get
> > the definitions?
> >
>
> Let me check this.
Well I created tester and it is working fine. Can you take a look on
"plain_c_tester.py" and modify it, so I can see the problem too.
Thanks
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Roman Y. <rom...@gm...> - 2008-02-17 17:30:10
|
On Feb 16, 2008 9:46 AM, Roman Yakovenko <rom...@gm...> wrote: > On Sat, Feb 16, 2008 at 3:29 AM, Julian Scheid <jul...@rs...> wrote: > > There's also another problem with this approach (both your patch and my > > similar fix): the API I'm wrapping is a rather large class hierarchy, > > and nearly all classes are derived from a common base class with a large > > number of virtual functions. > > > > Let's say for the sake of argument that it's 100 classes and 10 virtual > > functions in the common base class. This leads to 1000 times the wrapper > > functions generated, with almost identical code in each wrapper. I found > > that my Py++ wrapper library, which is already quite large at roughly 20 > > MB, gets blown up to over 40 MB once I include the base classes' virtual > > functions. > > > > I wonder if it would be possible to derive wrappers from the base class > > wrapper to help reduce this overhead? E.g. in my example, derive > > B_wrapper from A_wrapper? Ideally you could also reuse the registration > > code so that register_B_class would call something like > > register_A_class_virtuals. > > I should think about this. For some reason I thought that it could not > be done without > additional code provided by user. > > Let me check this one more time. I just checked this. It is very easy to patch Py++ to generate code in a new way, but after that .... Well, basically the compilation will fail on ambiguities. I attach source file, generated code and errors. If you think, I did it wrong or you will find a way that will make boost.python happy, than I will integrate your solution to Py++ :-) -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
|
From: Roman Y. <rom...@gm...> - 2008-02-16 19:03:58
|
On Feb 16, 2008 4:05 AM, Norma Zimmerman <nzi...@is...> wrote:
> Hi Roman,
Good evening
> Thanks for your help with my problem using std::vector<int>. As I said in my
> last email, my ultimate goal is to wrap functions with a signature similar
> to:
> UserDefinedReturnValue getDevices(std::vector<UserDefinedClass> &
> devices)
>
>
> I am have problems with a vector of a UserDefinedClass.
>
> I have the following class:
>
> #include <string>
> #include <iostream>
> #include <vector>
>
> using namespace std;
> enum iStorReturnType {SUCCESS, FAILURE};
> class Device
> {
> public:
> Device();
> iStorReturnType setName( string );
> iStorReturnType getName( string& );
> iStorReturnType printName();
> protected:
> string m_name;
> };
>
>
>
> In another class I have two instances of the Device class. In this class I
> have a function which returns one instance of the Device class with no
> problem. I want to also have a function to return a vector of all the
> devices.
>
>
>
> iStorReturnType getDevices(std::vector<Device>& devices);
>
>
>
> In my generated file I am seeing the following error:
>
>
>
> { //scope begin
>
> typedef bp::class_< std::vector< Device > >
> vector_less__Device__grate__exposer_t;
>
> vector_less__Device__grate__exposer_t
> vector_less__Device__grate__exposer =
> vector_less__Device__grate__exposer_t("vector_less__Device__grate_");
>
> bp::scope vector_less__Device__grate__scope(
> vector_less__Device__grate__exposer );
>
> //WARNING: the next line of code will not compile, because
> "::Device" does not have operator== !
>
> vector_less__Device__grate__exposer.def( bp::vector_indexing_suite<
> ::std::vector< Device > >() );
>
> } //scope end
>
>
>
> I am hoping this is the last stumbling block to being able to implement
> these "simple" classes. I would greatly appreciate any help you can give me.
If you can add operator== to your code. You don't have to modify the class,
you can implement is as free operator.
Or you can use "indexing suite v2". See
http://language-binding.net/pyplusplus/documentation/containers.html
> I do have one other question. In the C++ code that I am trying to wrap, all
> the functions have an error code as the return value and the actual values
> you want are passed as reference parameters. Is there a way to generate the
> function transformations other than listing each function separately in the
> python script which pyplusplus uses to generate the wrappers?
I thought this is an initial reason you started to use Py++ :-)
from pyplusplus import function_transformers as FT
mb =module_builder_t(...)
my_ns = mb.namespace( 'my namespace' )
for f in my_ns.calldefs():
if f.arguments[ -1 ].type.decl_string == "type that represent error":
f.add_transformation( FT.output( len( f.arguments ) - 1 )
Is this what you want?
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Roman Y. <rom...@gm...> - 2008-02-16 19:03:58
|
On Feb 16, 2008 8:25 PM, Gustavo Carneiro <gjc...@gm...> wrote:
> Hi. I am looking at scanning with pygccxml a pure C header file, that looks
> like this:
>
> #ifndef __HELLO_H__
> #define __HELLO_H__
>
> #ifdef __cplusplus
> extern "C"
> {
> #endif
>
>
> void hello_print(const char *message);
> double hello_sum(double x, double y);
>
>
> #ifdef __cplusplus
> }
> #endif
>
> #endif /* __HELLO_H__ */
>
> My current code, that woks for C++ headers perfectly, fails with this pure C
> header file:
>
> File "../pybindgen/gccxmlparser.py", line 416, in parse_init
> self.module_namespace =
> declarations.get_global_namespace(self.declarations)
> File
> "/usr/local//lib/python2.5/site-packages/pygccxml/declarations/algorithm.py",
> line 170, in get_global_namespace
> raise RuntimeError( "Unable to find global namespace." )
> RuntimeError: Unable to find global namespace.
>
> Any tips on what I should be using instead of get_global_namespace() to get
> the definitions?
>
Let me check this.
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Roman Y. <rom...@gm...> - 2008-02-16 18:52:22
|
On Feb 16, 2008 9:56 AM, Roman Yakovenko <rom...@gm...> wrote:
>
> On Sat, Feb 16, 2008 at 8:58 AM, Julian Scheid <jul...@rs...> wrote:
> > Julian Scheid wrote:
> > > Due to the way funcs.update works (?) this will put A.foo into "funcs"
> > > instead of B.foo when generating the wrapper for C. This in turn will
> > > lead to the following wrapper code for class C to be generated:
> >
> > To elaborate, the order in which "A::foo" and "B::foo" are traversed in
> > the "for f in funcs" loop depends on details of Python's Hashset
> > implementation - they might or might not be traversed in the right order
> > depending on how they are hashed. The right order being B::foo first and
> > then A::foo second so that B::foo is added and A::foo is later rejected
> > when tested with is_same_function.
> >
> > I haven't actually checked how things turn out for my hypothetical
> > example from the previous mail, if you can't reproduce it using that
> > example try using different class names (swapping A and B so that A is
> > derived from B and C is derived from A should do the trick).
> >
> > I found that this problem can be avoided simply by using a list instead
> > of a set for "funcs" and extend'ing it instead of update'ing it. While
> > possibly a tad less efficient, this seems to work fine and guarantees
> > that later on the right superclass is used.
> >
> > There is another intricacy. In the previous example (with classes A, B
> > and C) consider that mb.class_("B").member_functions("foo").exclude()
> > has been called. Now, if you use "not ignored and exportable" in the
> > query as I suggested originally, what happens is that only A.foo ends up
> > in "funcs" and the generated code for C_wrapper will incorrectly
> > dispatch to A::foo. What works better is either to disregard whether or
> > not a function is marked as ignore (downside being that exclude won't
> > affect derived classes) or, better, to filter the resulting list
> > "functions" at the very end of "redefined_funcs" and remove all methods
> > that are marked as ignore.
> >
> > My final results are attached as a patch. It seems to solve all issues
> > except for the overhead problem. (I was wrong about the static modifier
> > - this turned out not to be necessary.)
> >
> > Cheers,
> >
> > Julian
> >
> > --- class_wrapper.py 2008-02-16 17:52:10.000000000 +1100
> > +++ class_wrapper_derived_virtuals.py 2008-02-16 17:53:30.000000000 +1100
> > @@ -442,19 +442,20 @@
> > all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable )
> > all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included
> > all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL )
> > - all_not_pure_virtual = ~all_pure_virtual
> > + all_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.VIRTUAL ) & (declarations.access_type_matcher_t( 'public' ) | declarations.access_type_matcher_t( 'protected' ))
> > + all_not_pure_virtual = ~(all_pure_virtual | all_virtual)
> >
> > query = all_protected | all_pure_virtual
> > relevant_opers = declarations.custom_matcher_t( lambda decl: decl.symbol in ('()', '[]') )
> > - funcs = set()
> > + funcs = []
> > defined_funcs = set()
> >
> > for base in self.recursive_bases:
> > if base.access == ACCESS_TYPES.PRIVATE:
> > continue
> > base_cls = base.related_class
> > - funcs.update( base_cls.member_functions( query, allow_empty=True ) )
> > - funcs.update( base_cls.member_operators( relevant_opers & query, allow_empty=True ) )
> > + funcs.extend( base_cls.member_functions( query | (all_virtual & declarations.custom_matcher_t( lambda decl: decl.parent.alias == base_cls.alias )), allow_empty=True ) )
> > + funcs.extend( base_cls.member_operators( relevant_opers & query, allow_empty=True ) )
> >
> > defined_funcs.update( base_cls.member_functions( all_not_pure_virtual, allow_empty=True ) )
> > defined_funcs.update( base_cls.member_operators( all_not_pure_virtual & relevant_opers, allow_empty=True ) )
> > @@ -481,7 +482,7 @@
> > break
> > else:
> > not_reimplemented_funcs.add( f )
> > - functions = list( not_reimplemented_funcs )
> > + functions = filter( lambda f: not f.ignore and f.exportable, list( not_reimplemented_funcs ) )
> > functions.sort( cmp=lambda f1, f2: cmp( ( f1.name, f1.location.as_tuple() )
> > , ( f2.name, f2.location.as_tuple() ) ) )
> > self._redefined_funcs = functions
> >
> >
>
> Thank you very much!!!
>
> I am learning your patch and run through all my tests. If everything
> is okey I will commit it today.
Can I ask you to submit some kind of unit test - something very
simple, that will map your class hierarchy. I would like to be sure
next time I touch the code the things will continue to work.
Thanks
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Gustavo C. <gjc...@gm...> - 2008-02-16 18:25:08
|
Hi. I am looking at scanning with pygccxml a pure C header file, that looks
like this:
#ifndef __HELLO_H__
#define __HELLO_H__
#ifdef __cplusplus
extern "C"
{
#endif
void hello_print(const char *message);
double hello_sum(double x, double y);
#ifdef __cplusplus
}
#endif
#endif /* __HELLO_H__ */
My current code, that woks for C++ headers perfectly, fails with this pure C
header file:
File "../pybindgen/gccxmlparser.py", line 416, in parse_init
self.module_namespace = declarations.get_global_namespace(
self.declarations)
File
"/usr/local//lib/python2.5/site-packages/pygccxml/declarations/algorithm.py",
line 170, in get_global_namespace
raise RuntimeError( "Unable to find global namespace." )
RuntimeError: Unable to find global namespace.
Any tips on what I should be using instead of get_global_namespace() to get
the definitions?
Thanks in advance.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
|
|
From: Roman Y. <rom...@gm...> - 2008-02-16 07:56:31
|
On Sat, Feb 16, 2008 at 8:58 AM, Julian Scheid <jul...@rs...> wrote:
> Julian Scheid wrote:
> > Due to the way funcs.update works (?) this will put A.foo into "funcs"
> > instead of B.foo when generating the wrapper for C. This in turn will
> > lead to the following wrapper code for class C to be generated:
>
> To elaborate, the order in which "A::foo" and "B::foo" are traversed in
> the "for f in funcs" loop depends on details of Python's Hashset
> implementation - they might or might not be traversed in the right order
> depending on how they are hashed. The right order being B::foo first and
> then A::foo second so that B::foo is added and A::foo is later rejected
> when tested with is_same_function.
>
> I haven't actually checked how things turn out for my hypothetical
> example from the previous mail, if you can't reproduce it using that
> example try using different class names (swapping A and B so that A is
> derived from B and C is derived from A should do the trick).
>
> I found that this problem can be avoided simply by using a list instead
> of a set for "funcs" and extend'ing it instead of update'ing it. While
> possibly a tad less efficient, this seems to work fine and guarantees
> that later on the right superclass is used.
>
> There is another intricacy. In the previous example (with classes A, B
> and C) consider that mb.class_("B").member_functions("foo").exclude()
> has been called. Now, if you use "not ignored and exportable" in the
> query as I suggested originally, what happens is that only A.foo ends up
> in "funcs" and the generated code for C_wrapper will incorrectly
> dispatch to A::foo. What works better is either to disregard whether or
> not a function is marked as ignore (downside being that exclude won't
> affect derived classes) or, better, to filter the resulting list
> "functions" at the very end of "redefined_funcs" and remove all methods
> that are marked as ignore.
>
> My final results are attached as a patch. It seems to solve all issues
> except for the overhead problem. (I was wrong about the static modifier
> - this turned out not to be necessary.)
>
> Cheers,
>
> Julian
>
> --- class_wrapper.py 2008-02-16 17:52:10.000000000 +1100
> +++ class_wrapper_derived_virtuals.py 2008-02-16 17:53:30.000000000 +1100
> @@ -442,19 +442,20 @@
> all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable )
> all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included
> all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL )
> - all_not_pure_virtual = ~all_pure_virtual
> + all_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.VIRTUAL ) & (declarations.access_type_matcher_t( 'public' ) | declarations.access_type_matcher_t( 'protected' ))
> + all_not_pure_virtual = ~(all_pure_virtual | all_virtual)
>
> query = all_protected | all_pure_virtual
> relevant_opers = declarations.custom_matcher_t( lambda decl: decl.symbol in ('()', '[]') )
> - funcs = set()
> + funcs = []
> defined_funcs = set()
>
> for base in self.recursive_bases:
> if base.access == ACCESS_TYPES.PRIVATE:
> continue
> base_cls = base.related_class
> - funcs.update( base_cls.member_functions( query, allow_empty=True ) )
> - funcs.update( base_cls.member_operators( relevant_opers & query, allow_empty=True ) )
> + funcs.extend( base_cls.member_functions( query | (all_virtual & declarations.custom_matcher_t( lambda decl: decl.parent.alias == base_cls.alias )), allow_empty=True ) )
> + funcs.extend( base_cls.member_operators( relevant_opers & query, allow_empty=True ) )
>
> defined_funcs.update( base_cls.member_functions( all_not_pure_virtual, allow_empty=True ) )
> defined_funcs.update( base_cls.member_operators( all_not_pure_virtual & relevant_opers, allow_empty=True ) )
> @@ -481,7 +482,7 @@
> break
> else:
> not_reimplemented_funcs.add( f )
> - functions = list( not_reimplemented_funcs )
> + functions = filter( lambda f: not f.ignore and f.exportable, list( not_reimplemented_funcs ) )
> functions.sort( cmp=lambda f1, f2: cmp( ( f1.name, f1.location.as_tuple() )
> , ( f2.name, f2.location.as_tuple() ) ) )
> self._redefined_funcs = functions
>
>
Thank you very much!!!
I am learning your patch and run through all my tests. If everything
is okey I will commit it today.
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Roman Y. <rom...@gm...> - 2008-02-16 07:46:34
|
On Sat, Feb 16, 2008 at 3:29 AM, Julian Scheid <jul...@rs...> wrote: > There's also another problem with this approach (both your patch and my > similar fix): the API I'm wrapping is a rather large class hierarchy, > and nearly all classes are derived from a common base class with a large > number of virtual functions. > > Let's say for the sake of argument that it's 100 classes and 10 virtual > functions in the common base class. This leads to 1000 times the wrapper > functions generated, with almost identical code in each wrapper. I found > that my Py++ wrapper library, which is already quite large at roughly 20 > MB, gets blown up to over 40 MB once I include the base classes' virtual > functions. > > I wonder if it would be possible to derive wrappers from the base class > wrapper to help reduce this overhead? E.g. in my example, derive > B_wrapper from A_wrapper? Ideally you could also reuse the registration > code so that register_B_class would call something like > register_A_class_virtuals. I should think about this. For some reason I thought that it could not be done without additional code provided by user. Let me check this one more time. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
|
From: Roman Y. <rom...@gm...> - 2008-02-16 07:41:35
|
On Sat, Feb 16, 2008 at 3:06 AM, Julian Scheid <jul...@rs...> wrote: > I'm also not sure whether your only including public virtual functions > is correct. Unless I'm missing something, if you declare the "foo" > function in my original example protected instead of public you'd still > expect it to be overridable. The code we are dealing with, in this problem is very very fragile. So I prefer to enhanced it only for use cases I have real test cases. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
|
From: Julian S. <jul...@rs...> - 2008-02-16 06:58:20
|
Julian Scheid wrote:
> Due to the way funcs.update works (?) this will put A.foo into "funcs"
> instead of B.foo when generating the wrapper for C. This in turn will
> lead to the following wrapper code for class C to be generated:
To elaborate, the order in which "A::foo" and "B::foo" are traversed in
the "for f in funcs" loop depends on details of Python's Hashset
implementation - they might or might not be traversed in the right order
depending on how they are hashed. The right order being B::foo first and
then A::foo second so that B::foo is added and A::foo is later rejected
when tested with is_same_function.
I haven't actually checked how things turn out for my hypothetical
example from the previous mail, if you can't reproduce it using that
example try using different class names (swapping A and B so that A is
derived from B and C is derived from A should do the trick).
I found that this problem can be avoided simply by using a list instead
of a set for "funcs" and extend'ing it instead of update'ing it. While
possibly a tad less efficient, this seems to work fine and guarantees
that later on the right superclass is used.
There is another intricacy. In the previous example (with classes A, B
and C) consider that mb.class_("B").member_functions("foo").exclude()
has been called. Now, if you use "not ignored and exportable" in the
query as I suggested originally, what happens is that only A.foo ends up
in "funcs" and the generated code for C_wrapper will incorrectly
dispatch to A::foo. What works better is either to disregard whether or
not a function is marked as ignore (downside being that exclude won't
affect derived classes) or, better, to filter the resulting list
"functions" at the very end of "redefined_funcs" and remove all methods
that are marked as ignore.
My final results are attached as a patch. It seems to solve all issues
except for the overhead problem. (I was wrong about the static modifier
- this turned out not to be necessary.)
Cheers,
Julian
|
|
From: Julian S. <jul...@rs...> - 2008-02-16 05:44:55
|
Julian Scheid wrote:
> funcs.update( base_cls.member_functions( query | (all_virtual &
> declarations.custom_matcher_t( lambda decl: decl.parent.alias ==
> base_cls.alias and not decl.has_static and not decl.ignore and
> decl.exportable), allow_empty=True ) )
I found one more issue with my fix and I think your patch suffers from
the same problem. Consider this situation:
class A
{
public:
virtual void foo() {}
};
class B: public A
{
public:
virtual void foo() {}
};
class C: public B
{
}
Due to the way funcs.update works (?) this will put A.foo into "funcs"
instead of B.foo when generating the wrapper for C. This in turn will
lead to the following wrapper code for class C to be generated:
virtual void foo( ) {
if( bp::override func_foo = this->get_override( "foo" ) ) {
func_foo( );
} else
this->A::foo( );
}
Note it generates "this->A::foo" in the end where it actually should
invoke this->B:foo.
I haven't yet found a solution, simply reversing the base class list
used in the outer for loop doesn't seem to be enough.
Julian
|
|
From: Norma Z. <nzi...@is...> - 2008-02-16 02:05:16
|
Hi Roman,
Thanks for your help with my problem using std::vector<int>. As I said in my last email, my ultimate goal is to wrap functions with a signature similar to:
UserDefinedReturnValue getDevices(std::vector<UserDefinedClass> & devices)
I am have problems with a vector of a UserDefinedClass.
I have the following class:
#include <string>
#include <iostream>
#include <vector>
using namespace std;
enum iStorReturnType {SUCCESS, FAILURE};
class Device
{
public:
Device();
iStorReturnType setName( string );
iStorReturnType getName( string& );
iStorReturnType printName();
protected:
string m_name;
};
In another class I have two instances of the Device class. In this class I have a function which returns one instance of the Device class with no problem. I want to also have a function to return a vector of all the devices.
iStorReturnType getDevices(std::vector<Device>& devices);
In my generated file I am seeing the following error:
{ //scope begin
typedef bp::class_< std::vector< Device > > vector_less__Device__grate__exposer_t;
vector_less__Device__grate__exposer_t vector_less__Device__grate__exposer = vector_less__Device__grate__exposer_t("vector_less__Device__grate_");
bp::scope vector_less__Device__grate__scope( vector_less__Device__grate__exposer );
//WARNING: the next line of code will not compile, because "::Device" does not have operator== !
vector_less__Device__grate__exposer.def( bp::vector_indexing_suite< ::std::vector< Device > >() );
} //scope end
I am hoping this is the last stumbling block to being able to implement these "simple" classes. I would greatly appreciate any help you can give me.
I do have one other question. In the C++ code that I am trying to wrap, all the functions have an error code as the return value and the actual values you want are passed as reference parameters. Is there a way to generate the function transformations other than listing each function separately in the python script which pyplusplus uses to generate the wrappers?
Thanks so much for your help.
Norma
|
|
From: Julian S. <jul...@rs...> - 2008-02-16 01:29:32
|
Roman Yakovenko wrote: > Thank you very much for bug reporting. Few minutes ago I committed fix > and added new test case. > > The whole revision content: > http://pygccxml.svn.sourceforge.net/viewvc/pygccxml?view=rev&revision=1238 > > The fix: > http://pygccxml.svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py?r1=1238&r2=1237&pathrev=1238 > > I tested the fix again Py++ 0.9.5, but I guess it will also work for > your version too. There's also another problem with this approach (both your patch and my similar fix): the API I'm wrapping is a rather large class hierarchy, and nearly all classes are derived from a common base class with a large number of virtual functions. Let's say for the sake of argument that it's 100 classes and 10 virtual functions in the common base class. This leads to 1000 times the wrapper functions generated, with almost identical code in each wrapper. I found that my Py++ wrapper library, which is already quite large at roughly 20 MB, gets blown up to over 40 MB once I include the base classes' virtual functions. I wonder if it would be possible to derive wrappers from the base class wrapper to help reduce this overhead? E.g. in my example, derive B_wrapper from A_wrapper? Ideally you could also reuse the registration code so that register_B_class would call something like register_A_class_virtuals. Thanks, Julian |
|
From: Julian S. <jul...@rs...> - 2008-02-16 01:06:25
|
Roman Yakovenko wrote: >> This will not generate a wrapper for B even though B inherits A's >> virtual function. Now if I have the following Python code: >> >> class C(B): >> def foo(self): >> print "C.foo" >> >> ... then when foo() is invoked on this instance on the C++ side of >> things, the Python code won't be executed as the wrapper is missing. > > Thank you very much for bug reporting. Few minutes ago I committed fix > and added new test case. > > The whole revision content: > http://pygccxml.svn.sourceforge.net/viewvc/pygccxml?view=rev&revision=1238 > > The fix: > http://pygccxml.svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py?r1=1238&r2=1237&pathrev=1238 > > I tested the fix again Py++ 0.9.5, but I guess it will also work for > your version too. Thanks for your quick response. In the meantime I arrived at a similar solution but I found that just adding non-pure virtual functions to the "redefined_funcs" list alone, as in your patch, didn't do the trick. In addition, I had to do the following (this is against Py++ 0.9.0): - Make sure that the original function is not ignored and is exportable - Make sure it is not static (weird, I know, because static methods should never be virtual - yet for some reason a few static methods ended up in the query results.) - Make sure the original function is actually defined in the base class and not in an inner class of the base class. So my code looks roughly like this: funcs.update( base_cls.member_functions( query | (all_virtual & declarations.custom_matcher_t( lambda decl: decl.parent.alias == base_cls.alias and not decl.has_static and not decl.ignore and decl.exportable), allow_empty=True ) ) I might have a bug at another point in my generate_code.py so take this with a grain of salt - not sure why all of this is necessary. I'll try again with your HEAD and let you know how I go. Just a heads up that possibly it's not that trivial. I'm also not sure whether your only including public virtual functions is correct. Unless I'm missing something, if you declare the "foo" function in my original example protected instead of public you'd still expect it to be overridable. Thanks, Julian |
|
From: Roman Y. <rom...@gm...> - 2008-02-15 20:54:46
|
On Fri, Feb 15, 2008 at 3:22 AM, Julian Scheid <jul...@rs...> wrote:
> Hi,
>
> I ran into the following problem with Py++ 0.9.0.
>
> Consider this class hierarchy:
>
> class A
> {
> public:
> virtual void foo() {}
> };
>
> class B: public A
> {
> };
>
>
> This will not generate a wrapper for B even though B inherits A's
> virtual function. Now if I have the following Python code:
>
> class C(B):
> def foo(self):
> print "C.foo"
>
> ... then when foo() is invoked on this instance on the C++ side of
> things, the Python code won't be executed as the wrapper is missing.
>
> I managed to force generation of a wrapper for B, but even then it won't
> generate the necessary override code (virtual void foo, void
> default_foo, and the registration code.)
>
> My workaround is currently to manually add any implicit virtual
> functions that I need to override, but this is cumbersome and
> error-prone. Is there a way to configure or patch Py++ so that this is
> not necessary?
Thank you very much for bug reporting. Few minutes ago I committed fix
and added new test case.
The whole revision content:
http://pygccxml.svn.sourceforge.net/viewvc/pygccxml?view=rev&revision=1238
The fix:
http://pygccxml.svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py?r1=1238&r2=1237&pathrev=1238
I tested the fix again Py++ 0.9.5, but I guess it will also work for
your version too.
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Julian S. <jul...@rs...> - 2008-02-15 01:23:22
|
Hi,
I ran into the following problem with Py++ 0.9.0. Consider this class
hierarchy:
class A
{
public:
virtual void foo() {}
};
class B: public A
{
};
This will not generate a wrapper for B even though B inherits A's
virtual function. Now if I have the following Python code:
class C(B):
def foo(self):
print "C.foo"
... then when foo() is invoked on this instance on the C++ side of
things, the Python code won't be executed as the wrapper is missing.
I managed to force generation of a wrapper for B, but even then it won't
generate the necessary override code (virtual void foo, void
default_foo, and the registration code.)
My workaround is currently to manually add any implicit virtual
functions that I need to override, but this is cumbersome and
error-prone. Is there a way to configure or patch Py++ so that this is
not necessary?
Thanks in advance,
.Julian
|
|
From: Roman Y. <rom...@gm...> - 2008-02-14 06:12:40
|
On Thu, Feb 14, 2008 at 1:23 AM, Norma Zimmerman <nzi...@is...> wrote:
> I am having trouble wrapping C++ functions that have vectors as an argument.
> Ultimately, I want to be able to wrap functions with a signature similar to:
>
>
>
> UserDefinedReturnValue getDevice(std::vector<UserDefinedClass> &
> device)
>
>
>
> At the present time, I cannot correctly wrap the function getTimeVector from
> the following class.
>
>
>
> #include <string>
>
> #include <iostream>
>
> #include <vector>
>
> using namespace std;
>
> class ISS
>
> {
>
> public:
>
> ISS();
>
> void getTimeVector( std::vector<int> &);
>
> protected:
>
> int hour;
>
> int minute;
>
> int second;
>
> };
>
>
>
> In my generate_ISS.py module, I am adding nothing for the vector and am
> using the default
>
>
>
> import os
>
> from pyplusplus import module_builder
>
> from pyplusplus import function_transformers as FT
>
>
>
> #Creating an instance of class that will help you to expose your
> declarations
>
> mb = module_builder.module_builder_t( [r"C:/NJZsBoost/userAgent/real/ISS.h"]
>
> ,
> gccxml_path=r"C:/gccxml/build/bin/debug/gccxml.exe"
>
> ,
> working_directory=r"C:/NJZsBoost/userAgent/real"
>
> ,
> include_paths=['C:/NJZsBoost/userAgent/real']
>
> , define_symbols=[] )
>
>
>
> #Well, don't you want to see what is going on?
>
> mb.print_declarations()
>
>
>
> #Creating code creator. After this step you should not modify/customize
> declarations.
>
> mb.build_code_creator( module_name='py_ISS' )
>
>
>
> #Writing code to file.
>
> mb.write_module( './py_ISS.cpp' )
>
>
>
> My generated file contains the following.
>
> // This file has been generated by Py++.
>
> #include "boost/python.hpp"
>
> #include "__convenience.pypp.hpp"
>
> #include "__call_policies.pypp.hpp"
>
> #include "boost/python/suite/indexing/vector_indexing_suite.hpp"
>
> #include "c:/njzsboost/useragent/real/iss.h"
>
> namespace bp = boost::python;
>
>
>
> BOOST_PYTHON_MODULE(py_ISS){
>
> bp::class_< std::vector< int > >("vector_less__int__grate_")
>
> .def( bp::vector_indexing_suite< ::std::vector< int >, true >() );
>
>
>
> bp::class_< ISS >( "ISS" )
>
> .def( bp::init< >()
>
> .def(
>
> "getTimeVector"
>
> , &::ISS::getTimeVector
>
> , ( bp::arg("arg0") )
>
> }
>
>
>
> When I attempt to use the output from this, I get the following error
> message.
>
>
>
> >>> my_iss.getTimeVector()
>
> Traceback (most recent call last):
>
> File "<stdin>", line 1, in <module>
>
> Boost.Python.ArgumentError: Python argument types in
>
> ISS.getTimeVector(ISS)
>
> did not match C++ signature:
>
> getTimeVector(class ISS {lvalue}, class std::vector<int, class
> std::allocator<int> > {lvalue} arg0)
>
getTimeVector expects 1 argument, if you don't count self, try
times_vector = py_ISS.vector_less__int__grate_()
my_iss.getTimeVector( times_vector )
This should work
>
> I would appreciate it if you would show me an example similar to this. I
> would like to see:
>
>
>
> 1. what I should have in the pyplusplus.py file (my generate_ISS.py file)
Nothing, the problem was in your Python code. I suggest you to read
this document:
http://language-binding.net/pyplusplus/documentation/how_to/hints.html#class-template-instantiation-alias
> 2. what I should expect to see in the generated cpp file (my py_ISS.cpp
> file)
Nothing :-), the generated code works. Py++ has excellent unit tests (
http://pygccxml.svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/unittests/
)
> 3. how I use the wrapped function from python
>
> I am sorry for the chopped up examples but when I tried to send you a zipped
> folder containing a complete set of files, it was rejected because it was
> zipped. When I tried to attach the files, it was rejected because it was too
> large. I do have many things working in the class. I was able to get all the
> function transformations working. I have stripped all these from the files
> to save space. I am using Pyplusplus-0.9.5 and pygccxml-0.9.5.
>
As for me this post is a good example of how the problems should be presented.
>
> Thanks for any help you can give me.
HTH
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|
|
From: Norma Z. <nzi...@is...> - 2008-02-13 23:23:09
|
I am having trouble wrapping C++ functions that have vectors as an argument. Ultimately, I want to be able to wrap functions with a signature similar to:
UserDefinedReturnValue getDevice(std::vector<UserDefinedClass> & device)
At the present time, I cannot correctly wrap the function getTimeVector from the following class.
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class ISS
{
public:
ISS();
void getTimeVector( std::vector<int> &);
protected:
int hour;
int minute;
int second;
};
In my generate_ISS.py module, I am adding nothing for the vector and am using the default
import os
from pyplusplus import module_builder
from pyplusplus import function_transformers as FT
#Creating an instance of class that will help you to expose your declarations
mb = module_builder.module_builder_t( [r"C:/NJZsBoost/userAgent/real/ISS.h"]
, gccxml_path=r"C:/gccxml/build/bin/debug/gccxml.exe"
, working_directory=r"C:/NJZsBoost/userAgent/real"
, include_paths=['C:/NJZsBoost/userAgent/real']
, define_symbols=[] )
#Well, don't you want to see what is going on?
mb.print_declarations()
#Creating code creator. After this step you should not modify/customize declarations.
mb.build_code_creator( module_name='py_ISS' )
#Writing code to file.
mb.write_module( './py_ISS.cpp' )
My generated file contains the following.
// This file has been generated by Py++.
#include "boost/python.hpp"
#include "__convenience.pypp.hpp"
#include "__call_policies.pypp.hpp"
#include "boost/python/suite/indexing/vector_indexing_suite.hpp"
#include "c:/njzsboost/useragent/real/iss.h"
namespace bp = boost::python;
BOOST_PYTHON_MODULE(py_ISS){
bp::class_< std::vector< int > >("vector_less__int__grate_")
.def( bp::vector_indexing_suite< ::std::vector< int >, true >() );
bp::class_< ISS >( "ISS" )
.def( bp::init< >()
.def(
"getTimeVector"
, &::ISS::getTimeVector
, ( bp::arg("arg0") )
}
When I attempt to use the output from this, I get the following error message.
>>> my_iss.getTimeVector()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
ISS.getTimeVector(ISS)
did not match C++ signature:
getTimeVector(class ISS {lvalue}, class std::vector<int, class std::allocator<int> > {lvalue} arg0)
I would appreciate it if you would show me an example similar to this. I would like to see:
1. what I should have in the pyplusplus.py file (my generate_ISS.py file)
2. what I should expect to see in the generated cpp file (my py_ISS.cpp file)
3. how I use the wrapped function from python
I am sorry for the chopped up examples but when I tried to send you a zipped folder containing a complete set of files, it was rejected because it was zipped. When I tried to attach the files, it was rejected because it was too large. I do have many things working in the class. I was able to get all the function transformations working. I have stripped all these from the files to save space. I am using Pyplusplus-0.9.5 and pygccxml-0.9.5.
Thanks for any help you can give me.
Norma
|
|
From: Neal B. <ndb...@gm...> - 2008-02-12 17:27:12
|
I wonder if anyone can help with this? I'm trying to see what I can do with numpy. I have some test code I put in here: https://nbecker.dyndns.org/hg/numpy2/ It gives this error: gccxml_runtime_error_t: Error occured while running GCC-XML: /usr/include/boost/python/cast.hpp: In function 'Target* boost::python::detail::upcast(Source*, int*, int*, Target*) [with Source = PyArrayObject, Target = _object]': /usr/include/boost/python/cast.hpp:52: instantiated from 'static Target* boost::python::detail::upcaster<false>::execute(Source*, Target*) [with Source = PyArrayObject, Target = _object]' /usr/include/boost/python/cast.hpp:83: instantiated from 'Target* boost::python::detail::upcast_impl(Source*, Target*) [with Source = PyArrayObject, Target = _object]' /usr/include/boost/python/cast.hpp:92: instantiated from 'Target* boost::python::upcast(Source*, Target*) [with Target = _object, Source = PyArrayObject]' /usr/include/boost/python/refcount.hpp:36: instantiated from 'void boost::python::xdecref(T*) [with T = PyArrayObject]' /usr/include/boost/python/handle.hpp:211: instantiated from 'boost::python::handle<T>::~handle() [with T = PyArrayObject]' numpy_iter.hpp:92: instantiated from here /usr/include/boost/python/cast.hpp:31: error: no type named 'type' in 'struct boost::python::base_type_traits<PyArrayObject>' /usr/include/boost/python/cast.hpp:33: error: no type named 'type' in 'struct boost::python::base_type_traits<PyArrayObject>' Any ideas? |
|
From: Roman Y. <rom...@gm...> - 2008-02-05 19:54:38
|
Good evening. I would like to announce a new version of both projects. Both projects contain many new features: pygccxml: * support for new GCC-XML version, which is based in GCC 4.2 parser * ability to create template instantiated class name, without default template arguments. For example, for class "vector< int, std::allocator< int > >" pygccxml could produce "vector<int>". * see http://language-binding.net/pygccxml/history/history.html#version-0-9-5 for more detailed list of changes Py++ contains much more features: * full support for UNICODE * better support for the multi-module development was implement * one more strategy to split generated code to files. The user defines a number of files to split the generated code too and Py++ does the rest. * this release contains bulk of small usability features and documentation improvements. * improved unit tests framework * seehttp://language-binding.net/pyplusplus/history/history.html#version-0-9-5 for more detailed list of changes I would like to thank anyone who contributed to this release. As always comments, suggestions & bug reports are welcome. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
|
From: Roman Y. <rom...@gm...> - 2008-01-15 14:35:25
|
On Jan 15, 2008 4:14 PM, Allen Bierbaum <al...@vr...> wrote: > Is there a way to detect this problem is happening and output an error > with a link to the documentation? The way it works now where it > generates code that doesn't compile seems a bit problematic to me. I > don't think a new user would be able to decipher what is going on and > determine what they need to fix. If I would now to detect such use case I would treat them in Py++. For free and non virtual member functions you can use next functionality http://language-binding.net/pyplusplus/documentation/functions/default_args.html What user you mean by "a new user" - a bindings developer or final user, who will run the script and compile generated code? -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
|
From: Allen B. <al...@vr...> - 2008-01-15 14:14:51
|
Is there a way to detect this problem is happening and output an error
with a link to the documentation? The way it works now where it
generates code that doesn't compile seems a bit problematic to me. I
don't think a new user would be able to decipher what is going on and
determine what they need to fix.
-Allen
Roman Yakovenko wrote:
> On Jan 15, 2008 1:02 AM, Allen Bierbaum <al...@vr...> wrote:
>> I am wrapping a method that looks something like this:
>>
>> class MyClass
>> {
>> public:
>> void init(const unsigned value=0,
>> const ClassB valueb=ClassB(-10.0, 11.0),
>> const float other_val=2.0);
>> };
>>
>> When py++ wraps this it creates code like this:
>>
>> { //::MyClass::init
>>
>> typedef void ( ::MyClass::*init_function_type )( ::unsigned
>> const,::ClassB const,::float const ) ;
>>
>> MyClass_exposer.def( "init"
>> , init_function_type( &::MyClass::init )
>> , ( bp::arg("value")=(unsigned char const)(0)
>> , bp::arg("valueb")=::ClassB( (&-1.0e+1), (&1.1e+1)
>> , bp::arg("other_val")=2.0e+0 ) );
>> }
>>
>> As you can see the "&-1.0e+1" style values are invalid code and the
>> compiler fails to build the code. Is this a know issue and is there a
>> simple work around or way to prevent py++ from generating code that
>> won't compile?
>
> Yes, this is a known issue -
> http://language-binding.net/pygccxml/design.html#patchers
>
> You have few ways to fix the problem:
> http://language-binding.net/pyplusplus/documentation/functions/default_args.html
> or
> mb = module_builder_t(...)
> mb.mem_fun( '::MyClass::init' ).arguments[1].default_value =
> 'ClassB(-10.0, 11.0)'
>
> Choose the one you like
>
> HTH
>
|
|
From: Roman Y. <rom...@gm...> - 2008-01-15 06:39:10
|
On Jan 15, 2008 1:02 AM, Allen Bierbaum <al...@vr...> wrote:
> I am wrapping a method that looks something like this:
>
> class MyClass
> {
> public:
> void init(const unsigned value=0,
> const ClassB valueb=ClassB(-10.0, 11.0),
> const float other_val=2.0);
> };
>
> When py++ wraps this it creates code like this:
>
> { //::MyClass::init
>
> typedef void ( ::MyClass::*init_function_type )( ::unsigned
> const,::ClassB const,::float const ) ;
>
> MyClass_exposer.def( "init"
> , init_function_type( &::MyClass::init )
> , ( bp::arg("value")=(unsigned char const)(0)
> , bp::arg("valueb")=::ClassB( (&-1.0e+1), (&1.1e+1)
> , bp::arg("other_val")=2.0e+0 ) );
> }
>
> As you can see the "&-1.0e+1" style values are invalid code and the
> compiler fails to build the code. Is this a know issue and is there a
> simple work around or way to prevent py++ from generating code that
> won't compile?
Yes, this is a known issue -
http://language-binding.net/pygccxml/design.html#patchers
You have few ways to fix the problem:
http://language-binding.net/pyplusplus/documentation/functions/default_args.html
or
mb = module_builder_t(...)
mb.mem_fun( '::MyClass::init' ).arguments[1].default_value =
'ClassB(-10.0, 11.0)'
Choose the one you like
HTH
--
Roman Yakovenko
C++ Python language binding
http://www.language-binding.net/
|