Hello, thanks to your helpful replies, I think I got one step closer to understanding how Py++ should work :) I built a python script that dynamically creates a header file including all the libraries from one folder. Fortunately, each class is contained in one single header called <classname>.h, so that creating the template typedefs and instantiations work fine. Now my understanding is still lacking with respect to template functions: I followed the howto-advise and call every function once for instantiation. This works, however I need to control the name that function later has in Python. At the moment I use function pointers (I could not find something like typedef), but they don't seem to make their way into the Boost.Python binding file. --- Now something from my tests: I noticed I often get a error like super(type, obj): obj must be instance or subtype of type. from a condition in decl_wrappers/calldef_wrapper.py (line 309). However, running your GUI utility for a test, this error never occurs. What is my mistake? --- Another problem arises when I try to build an example I created for my lib: I always run into 'boost::python::init' : too many template arguments errors. I had no time to dive deeper into Boost.Python, anyone up for a quick heads-up? --- This is all :D I really appreciate your efforts in helping out, and I am confident Py++ results will soon overtake Swig and pay off the time invested. Regards, N.
On 8/31/06, Nicolas Tessore <wz_@gmx.net> wrote:
I built a python script that dynamically creates a header file including all the libraries from one folder. Fortunately, each class is contained in one single header called <classname>.h, so that creating the template typedefs and instantiations work fine.
:-)
Now my understanding is still lacking with respect to template functions: I followed the howto-advise and call every function once for instantiation. This works, however I need to control the name that function later has in Python. At the moment I use function pointers (I could not find something like typedef), but they don't seem to make their way into the Boost.Python binding file.
Please read these tutorials: http://language-binding.net/pyplusplus/documentation/tutorials/module_builde...
---
Now something from my tests: I noticed I often get a error like
super(type, obj): obj must be instance or subtype of type.
from a condition in decl_wrappers/calldef_wrapper.py (line 309). However, running your GUI utility for a test, this error never occurs. What is my mistake?
I am not sure that this is your mistake. Can you create small script that reproduce the error?
---
Another problem arises when I try to build an example I created for my lib: I always run into
'boost::python::init' : too many template arguments
errors. I had no time to dive deeper into Boost.Python, anyone up for a quick heads-up?
You don't read Py++ warnings, right? The function has more than %d arguments ( %d ). You should adjust BOOST_PYTHON_MAX_ARITY macro. For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html You should find this message in your output script, where first %d will be 10, and second %d will contain actual number of arguments. Please read them, you will save a lot of time.
---
This is all :D I really appreciate your efforts in helping out, and I am confident Py++ results will soon overtake Swig and pay off the time invested.
We will see. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Roman Yakovenko wrote:
Please read these tutorials: http://language-binding.net/pyplusplus/documentation/tutorials/module_builde...
I did, though I fear I am too underexperienced to see any direct connection to my problem. Or did I misspell my problem? The situation is the following: I have a base class MyClass. From it, I derive HisClass and HerClass. Then I have a function DynamicCast<T>(MyClass *) and another one called(MyClass *) StaticCast<T> which are used to cast one of MyClass's derivatives into another, ie. HisClass h1; HerClass h2; h2 = DynamicCast<HisClass>(h2); Now sorry if I am turning around here, and you answered this already. If so, please tell me and I will stop asking until I get the knack myself. :) I then used a helper to write my special Py++ header: 01: /* The cast object */ 02: MyClass *CastObj; 03: 04: /* Cast every object once to make it known to Py++ */ 05: DynamicCast<HisClass>(CastObj); 06: DynamicCast<HerClass>(CastObj); 07: ... This produces a result in my binding source file. I understood I then have to rename the functions, but is there a way to do this in a pattern-like way so I can rename all DynamicCast<T> to DynamicCastToT in one step? Though I just checked that using a loop for renaming them "manually" should work as well.
I am not sure that this is your mistake. Can you create small script that reproduce the error?
Unfortunately, I cannot. It does not happen on smaller test projects, and only occasionally on the library now.
You don't read Py++ warnings, right?
I try to, but it is a bit hard to spot this one in 11237 lines of output. Especially if you are unsure what to look for. Still I am happy to get more and more functionality to work :) Best regards, N.
On 8/31/06, Nicolas Tessore <wz_@gmx.net> wrote:
I did, though I fear I am too underexperienced to see any direct connection to my problem. Or did I misspell my problem? The situation is the following:
I have a base class MyClass. From it, I derive HisClass and HerClass.
Then I have a function DynamicCast<T>(MyClass *) and another one called(MyClass *) StaticCast<T> which are used to cast one of MyClass's derivatives into another, ie.
HisClass h1; HerClass h2; h2 = DynamicCast<HisClass>(h2);
Now sorry if I am turning around here, and you answered this already. If so, please tell me and I will stop asking until I get the knack myself. :)
I then used a helper to write my special Py++ header:
01: /* The cast object */ 02: MyClass *CastObj; 03: 04: /* Cast every object once to make it known to Py++ */ 05: DynamicCast<HisClass>(CastObj); 06: DynamicCast<HerClass>(CastObj); 07: ...
This is what I understand until now: struct MyClass{...}; struct HisClass : MyClass {}; struct HerClass : MyClass {}; And you want to cast from HisClass to HerClass, right? ( I don't want to know why you have to do this, really :) ) If HisClass derives from HerClass, than you don't need to introduce casting. http://www.boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#...
This produces a result in my binding source file. I understood I then have to rename the functions, but is there a way to do this in a pattern-like way so I can rename all DynamicCast<T> to DynamicCastToT in one step? Though I just checked that using a loop for renaming them "manually" should work as well.
I am not sure that this is your mistake. Can you create small script
from pygccxml import declarations def rename_cast( cast ): cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name ) casts = mb.free_functions( lambda decl: decl.name.startswith( 'DynamicCast<' ) ) map( rename_cast, casts ) that
reproduce the error?
Unfortunately, I cannot. It does not happen on smaller test projects, and only occasionally on the library now.
May be you can debug the code? I can do it too, but you will have to send me GCCXML generated xml file and script that reporoduce the error. C++ source code is not requiered.
You don't read Py++ warnings, right?
I try to, but it is a bit hard to spot this one in 11237 lines of output. Especially if you are unsure what to look for.
By default Py++ prints all messages, formatted to feat your console width. You can redefine this functionality and print a message into file and all message could be written within one line. After this you can use grep to find and monitor interesting messages. Read this section of docs: http://language-binding.net/pyplusplus/documentation/feedback.html -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Roman Yakovenko wrote:
This is what I understand until now:
struct MyClass{...}; struct HisClass : MyClass {}; struct HerClass : MyClass {};
And you want to cast from HisClass to HerClass, right? ( I don't want to know why you have to do this, really :) )
That's right. This is the way the lib is build.
If HisClass derives from HerClass, than you don't need to introduce casting.
I have to, they are siblings, not ancestors. Even if, I have to use what I'm given by the library.
from pygccxml import declarations
def rename_cast( cast ): cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
casts = mb.free_functions ( lambda decl: decl.name.startswith( 'DynamicCast<' ) ) map( rename_cast, casts )
This always leaves me with a "query returned no matches" error :(
May be you can debug the code? I can do it too, but you will have to send me GCCXML generated xml file and script that reporoduce the error. C++ source code is not requiered.
I cannot even reproduce it anymore myself. I will try to go back to my original tests, and see if I can bring it up again. Thanks for the continued effort! N.
from pygccxml import declarations
def rename_cast( cast ): cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
casts = mb.free_functions ( lambda decl: decl.name.startswith( 'DynamicCast<' ) ) map( rename_cast, casts )
This always leaves me with a "query returned no matches" error :( Ok, I figured this out myself. GCCXML does not save the template part of
Nicolas Tessore wrote: the name, so all those functions are called "DynamicCast". I slightly modified your approach: 01: #Find object type in Casts. Const T casts are ignored 02: pattern = "::Mylib::Ref<Mylib::(.*)>" 03: p = re.compile(pattern) 04: 05: def rename_casts( cast ): 06: m = p.match(cast.return_type.decl_string) 07: if m: 08: cast.rename( cast.name + 'To' + m.groups()[0] ) 09: else: #DynamicCast should be excluded 10: cast.exclude() 11: 12: casts = mb.free_functions ( lambda decl: ( decl.name == 'DynamicCast' or decl.name == 'StaticCast' ) ) 13: map( rename_casts, casts ) This works beautifully :) But is it a correct approach? And it clearly shows I barely scratched the surface of the power that Py++/ pygccxml hold :/ Now while still giggling at the wonderful result I saw, it happened that I noticed my typedefs à la typedef Mylib::Ref<Mylib::MyClass> MyClassRef; sizeof(MyClassRef); are not automatically detected and thus, the Mylib::Ref<Mylib::MyClass> is still named Mylib_scope_Ref_less_than_Mylib_scope_MyClass_grate etc in the generated binding source. Any clues why that could be? It is not a problem though, I will just apply the same method as above to them. The road goes ever on and on , N.
On 9/1/06, Nicolas Tessore <wz_@gmx.net> wrote:
from pygccxml import declarations
def rename_cast( cast ): cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
casts = mb.free_functions ( lambda decl: decl.name.startswith( 'DynamicCast<' ) ) map( rename_cast, casts )
This always leaves me with a "query returned no matches" error :( Ok, I figured this out myself. GCCXML does not save the template part of
Nicolas Tessore wrote: the name, so all those functions are called "DynamicCast". I slightly modified your approach:
01: #Find object type in Casts. Const T casts are ignored 02: pattern = "::Mylib::Ref<Mylib::(.*)>" 03: p = re.compile(pattern) 04: 05: def rename_casts( cast ): 06: m = p.match(cast.return_type.decl_string) 07: if m: 08: cast.rename( cast.name + 'To' + m.groups()[0] ) 09: else: #DynamicCast should be excluded 10: cast.exclude() 11: 12: casts = mb.free_functions ( lambda decl: ( decl.name == 'DynamicCast' or decl.name == 'StaticCast' ) ) 13: map( rename_casts, casts )
This works beautifully :) But is it a correct approach?
If it works, that the answer is yes.
And it clearly shows I barely scratched the surface of the power that Py++/ pygccxml hold :/
Please take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates... The functionality provided by this module will do the job for you. But you ignored my advice: cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name ) You don't have to parse, just extract class declaration from DynamicCast return type.
Now while still giggling at the wonderful result I saw, it happened that I noticed my typedefs à la
typedef Mylib::Ref<Mylib::MyClass> MyClassRef; sizeof(MyClassRef);
are not automatically detected and thus, the Mylib::Ref<Mylib::MyClass> is still named Mylib_scope_Ref_less_than_Mylib_scope_MyClass_grate etc in the generated binding source. Any clues why that could be? It is not a problem though, I will just apply the same method as above to them.
Read this: http://language-binding.net/pyplusplus/documentation/hints.html It should explain why Py++ does not work as you expects. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Roman Yakovenko wrote:
Please take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates... The functionality provided by this module will do the job for you. I guess I should start searching both docs more. Thanks for the heads-up.
But you ignored my advice:
cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
You don't have to parse, just extract class declaration from DynamicCast return type.
No, the return type is not the right kind. This is due to the fact that Mylib::Ref<T> is used as a pointer to T. Still the return type is T*.
Read this: http://language-binding.net/pyplusplus/documentation/hints.html It should explain why Py++ does not work as you expects.
Yes, I saw that and thus want to do it in the script :) N.
On 9/1/06, Nicolas Tessore <wz_@gmx.net> wrote:
Roman Yakovenko wrote:
Please take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates... The functionality provided by this module will do the job for you. I guess I should start searching both docs more. Thanks for the heads-up.
But you ignored my advice:
cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
You don't have to parse, just extract class declaration from DynamicCast return type.
No, the return type is not the right kind. This is due to the fact that Mylib::Ref<T> is used as a pointer to T. Still the return type is T*.
Take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.type_trai... P++ via pygccxml provides a lot of "type_traits" functionality found in boost.type_traits library: http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.type_trai...
Read this: http://language-binding.net/pyplusplus/documentation/hints.html It should explain why Py++ does not work as you expects.
Yes, I saw that and thus want to do it in the script :)
http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.class_dec... Take a look on the documentation. May be you will be able to implement custom logic that will assign aliases automatically -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Roman Yakovenko wrote:
Please take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates... The functionality provided by this module will do the job for you.
But you ignored my advice:
cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
You don't have to parse, just extract class declaration from DynamicCast return type.
Ok, I even understood that now: 01: def rename_casts( cast ): 02: cast_to = declarations.templates.args(cast.decl_string)[0].rsplit('::', 2)[-1] 03: cast.rename( cast.name + 'To' + cast_to) 04: 05: def rename_refs( ref ): 06: ref_to = declarations.templates.args(ref.decl_string)[0].rsplit('::', 2)[-1] 07: ref.rename( ref_to + "Ref" ) 08: 09: refs = mb.classes ( lambda decl: ( decl.name.startswith('Ref<') ) ) 10: map( rename_refs, refs ) 11: 12: casts = mb.free_functions ( lambda decl: ( decl.name == 'DynamicCast' or decl.name == 'StaticCast' ) ) 13: map( rename_casts, casts ) This leaves me with a build error, yelling at me that I should specify a call policy. Am I right this is not currently supported by Py++? At least my google searches told me so. N.
On 9/1/06, Nicolas Tessore <wz_@gmx.net> wrote:
Roman Yakovenko wrote:
Please take a look on http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates... The functionality provided by this module will do the job for you.
But you ignored my advice:
cls_to = declarations.class_traits.get_declaration( cast.return_type ) cast.rename( 'DynamicCastTo' + cls_to.name )
You don't have to parse, just extract class declaration from DynamicCast return type.
Ok, I even understood that now:
01: def rename_casts( cast ): 02: cast_to = declarations.templates.args(cast.decl_string)[0].rsplit('::', 2)[-1] 03: cast.rename( cast.name + 'To' + cast_to) 04: 05: def rename_refs( ref ): 06: ref_to = declarations.templates.args(ref.decl_string)[0].rsplit('::', 2)[-1] 07: ref.rename( ref_to + "Ref" ) 08: 09: refs = mb.classes ( lambda decl: ( decl.name.startswith('Ref<') ) ) 10: map( rename_refs, refs ) 11: 12: casts = mb.free_functions ( lambda decl: ( decl.name == 'DynamicCast' or decl.name == 'StaticCast' ) ) 13: map( rename_casts, casts )
This leaves me with a build error, yelling at me that I should specify a call policy. Am I right this is not currently supported by Py++? At least my google searches told me so.
API docs: http://language-binding.net/pyplusplus/documentation/apidocs/pyplusplus.decl... http://language-binding.net/pyplusplus/documentation/apidocs/pyplusplus.decl... Tutorials: http://language-binding.net/pyplusplus/documentation/tutorials/module_builde... http://language-binding.net/pyplusplus/documentation/tutorials/module_builde... -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
participants (2)
-
Nicolas Tessore -
Roman Yakovenko