Re: [pygccxml-development] Function adaptors
Brought to you by:
mbaas,
roman_yakovenko
From: Berserker <ber...@ho...> - 2009-08-18 10:04:38
|
> Actually yes: http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1754&view=rev > I also attach a file, the Py++ tester generated. Follow the comments > and I think you will be fine. No need to deal with Py++ internals. You really made my life easier with this patch, thanks! Unfortunately I still have a (little) problem with virtual protected methods :) Let's consider the "Foo" class: > class Foo() > { > public: > Foo(){} > virtual ~Foo(){} > public: > virtual void public_virtual(){} > protected: > virtual void protected_virtual(){} > }; Base on revision 1754, the wrapper's code generated for "public_virtual" is splitted in: - Foo_wrapper::default_public_virtual: this is the case of a Python to C++ function call, here I unlock the GIL allowing others interpreters to run Python code during the Foo::public_virtual execution where no CPython API will be called - Foo_wrapper::public_virtual (C++ to Python call): this is the case of a C++ to Python function call (as I the "JobsManager" sample that I've posted before) and here, as exaplained, I need to restore the correct PyThreadState. Everything works fine here :D, the problem is related to protected_virtual method where Py++ only generates Foo_wrapper::protected_virtual code (why?). Now consider this Python code: > class PyFoo(Foo): > def test_public_virtual(self): > self.public_virtual() > > def public_virtual(self): > Foo.public_virtual(self) > > def test_protected_virtual(self): > self.protected_virtual() > > def protected_virtual(self): > Foo.protected_virtual(self) > > foo = PyFoo() > foo.test_virtual_public() > foo.test_virtual_protected() foo.test_public_virtual() calls PyFoo.public_virtual() which calls Foo_wrapper::default_public_virtual() which calls Foo::public_virtual() (as expected) foo.test_protected_virtual() calls PyFoo.protected_virtual() which calls Foo_wrapper::protected_virtual() insted of a "Foo_wrapper::default_protected_virtual()", let's see the code of "Foo_wrapper::protected_virtual()" (without "customizations") > virtual void protected_virtual( ){ > if( ::boost::python::override func_protected_virtual = this->get_override( "protected_virtual" ) ) > func_protected_virtual( ); > else{ > this->::Foo::protected_virtual( ); > } > } Do you see the problem here? "func_protected_virtual" will always lead in a "true" condition because of our PyFoo.protected_virtual, so func_protected_virtual() invokes the Python code which in turn invokes the C++ wrapper code infinitely. I think that it will be easy to fix this problem (we just need to create a Foo_wrapper::default_protected_virtual as for the virtual public functions). > May I ask you to create an article or document, with examples, which > explains how to use Py++ for embedding? Sure, I'd like to help you in writing an "embedding tutorial" but I need to fix the last issues in my TODO, for example I noticed that in this release you make use of "boost::python::pure_virtual" which is correct but causes me lots of headaches :) , here is a short explanation of the problem: ""boost::python::pure_virtual" is a custom "visitor" that adds a default implementation (function "pure_virtual_called") which raises an exception. Here it is the code: > void BOOST_PYTHON_DECL pure_virtual_called() > { > PyErr_SetString(PyExc_RuntimeError, "Pure virtual function called"); > throw_error_already_set(); > } In the case of a C++ to Python calls, I would need, as usual, to restore the right PyThreadState before calling any CPython API (PyErr_SetString in the above's code), but I have no options here to customize "pure_virtual_called". Probably I'll ovverride in Py++ the identifier "::boost::python::pure_virtual" with a custom one, but I still need to think/work on this (I love the "override" feature in Py++ :) ). The last problem I want to report is in the files name generation: they follow the classes names (in the "Foo" example Py++ creates a "Foo.pypp.cpp" file) but in the registration code (where BOOST_PYTHON_MODULE is defined), the include code is always in lower case (#include "foo.pypp.cpp" in our example) and this causes problems when I compile the code under linux. Actually I'm using this workaround: > original_write_file = pyplusplus.file_writers.multiple_files.multiple_files_t.write_file > def make_lower_write_file(self, fpath, content): > splittedPath = os.path.split(fpath) > fpath = os.path.join(splittedPath[0], splittedPath[1].lower()) > original_write_file(self, fpath, content) > pyplusplus.file_writers.multiple_files.multiple_files_t.write_file = make_lower_write_file Thanks again for making my life easier, I hope to solve the "protected" issue (and others too...) soon :) Bye _________________________________________________________________ Scarica i nuovi gadget per personalizzare Messenger! http://www.messenger.it/home_gadget.aspx |