From nicodemus at esss.com.br Mon Jan 3 20:23:02 2005 From: nicodemus at esss.com.br (Nicodemus) Date: Mon, 03 Jan 2005 16:23:02 -0300 Subject: [C++-sig] Re: Pyste patch: fix 3 bugs and add new-style polymorphism In-Reply-To: <007101c4dd75$72b28230$0200a8c0@lain> References: <007101c4dd75$72b28230$0200a8c0@lain> Message-ID: <41D99B96.90402@esss.com.br> Hi Baptiste, Baptiste Lepilleur wrote: >The attached patch fixes the following bugs in pyste: > > > Thanks a lot for the patch! Sorry for taking so long to respond, I moved recently and was without an internet connection until now. I applied your patch, but I'm having trouble compiling the generated file with the latest Boost-CVS. I'm using MSVC 6.0 on Windows XP. The command line used was: cl /nologo /Zm200 /LD /YX /GR /GX -I. -Id:/programming/libraries/boost-cvs/boost -Id:/bin/python/include new.cpp /link /libpath:d:/bin/python/libs /libpath:d:/programming/libraries/boost-cvs/lib /dll boost_python.lib The source file is attached. Does anyone have an idea of what the problem is? Best Regards, Bruno. -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: new.cpp URL: From gaiacrtn at free.fr Mon Jan 3 22:39:04 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Mon, 3 Jan 2005 22:39:04 +0100 Subject: [C++-sig] Re: Pyste patch: fix 3 bugs and add new-style polymorphism References: <007101c4dd75$72b28230$0200a8c0@lain> <41D99B96.90402@esss.com.br> Message-ID: <01cf01c4f1dc$a9a0e6d0$0200a8c0@lain> I never tried building on VC++ 6 (I'm already struggling with VC++ 7.1 limits). I attached the build log with the errors. Basically many errors like: E:\prg\vc\Lib\boost_1_32_0\boost/python/class.hpp(404) : error C2657: '`global namespace'::*' found at the start of a statement (did you forget to specify a type?) E:\prg\vc\Lib\boost_1_32_0\boost/python/class.hpp(381) : see reference to function template instantiation 'class boost::python::api::object __thiscall boost::python::?$class_ at UVirtualNonCopyable_Wrapper@?%new.cpp253401447@@Vnon copyable at noncopyable_@boost@@Unot_specified at detail@python at 5@U6785@::make_fn_ impl(int *,class std::basic_string,class std::allocator > VirtualNonCopyable::*,struct boost::mpl::bool_<0>,char *,struct boost::mpl::bool_<1>)' being compiled template object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_) { D T::*pm = pm_; /// <=== line 404 of class.hpp return python::make_getter(pm); } It doesn't make sense for me. A compiler bug ? Baptiste. ----- Original Message ----- From: "Nicodemus" To: Cc: "Baptiste Lepilleur" Sent: Monday, January 03, 2005 8:23 PM Subject: [C++-sig] Re: Pyste patch: fix 3 bugs and add new-style polymorphism > Hi Baptiste, > > Baptiste Lepilleur wrote: > > >The attached patch fixes the following bugs in pyste: > > > > > > > > Thanks a lot for the patch! Sorry for taking so long to respond, I moved > recently and was without an internet connection until now. > > I applied your patch, but I'm having trouble compiling the generated > file with the latest Boost-CVS. I'm using MSVC 6.0 on Windows XP. The > command line used was: > > cl /nologo /Zm200 /LD /YX /GR /GX -I. > -Id:/programming/libraries/boost-cvs/boost -Id:/bin/python/include > new.cpp /link /libpath:d:/bin/python/libs > /libpath:d:/programming/libraries/boost-cvs/lib /dll boost_python.lib > > The source file is attached. Does anyone have an idea of what the > problem is? > > Best Regards, > Bruno. > ---------------------------------------------------------------------------- ---- > > // Boost Includes ============================================================== > #include > #include > > // Includes ==================================================================== > #include > > // Using ======================================================================= > using namespace boost::python; > > // Declarations ================================================================ > namespace { > > BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(NonVirtual_set_overloads_1_3, set, 1, 3) > > struct VirtualNonCopyable_Wrapper: VirtualNonCopyable, wrapper< VirtualNonCopyable > > { > VirtualNonCopyable_Wrapper(): > VirtualNonCopyable() {} > > void set(const std::string& p0, int p1, int p2) { > if (override f = this->get_override("set")) > call< void >( f.ptr(), p0, p1, p2); > VirtualNonCopyable::set(p0, p1, p2); > } > > static void default_set_1(VirtualNonCopyable &self, const std::string& p0) { > self.set(p0); > } > > static void default_set_2(VirtualNonCopyable &self, const std::string& p0, int p1) { > self.set(p0, p1); > } > > void default_set(const std::string& p0, int p1, int p2) { > VirtualNonCopyable::set(p0, p1, p2); > } > > }; > > BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(NonVirtualReturnValuePolicy_set_overl oads_1_3, set, 1, 3) > > struct VirtualReturnValuePolicy_Wrapper: VirtualReturnValuePolicy, wrapper< VirtualReturnValuePolicy > > { > VirtualReturnValuePolicy_Wrapper(): > VirtualReturnValuePolicy() {} > > ValueHolder* set(const std::string& p0, int p1, int p2) { > if (override f = this->get_override("set")) > return call< ValueHolder* >( f.ptr(), p0, p1, p2); > return VirtualReturnValuePolicy::set(p0, p1, p2); > } > > static ValueHolder* default_set_1(VirtualReturnValuePolicy &self, const std::string& p0) { > return self.set(p0); > } > > static ValueHolder* default_set_2(VirtualReturnValuePolicy &self, const std::string& p0, int p1) { > return self.set(p0, p1); > } > > ValueHolder* default_set(const std::string& p0, int p1, int p2) { > return VirtualReturnValuePolicy::set(p0, p1, p2); > } > > ValueHolder* set(int p0, int p1) { > if (override f = this->get_override("set")) > return call< ValueHolder* >( f.ptr(), p0, p1); > return VirtualReturnValuePolicy::set(p0, p1); > } > > static ValueHolder* default_set_0(VirtualReturnValuePolicy &self) { > return self.set(); > } > > static ValueHolder* default_set_1(VirtualReturnValuePolicy &self, int p0) { > return self.set(p0); > } > > ValueHolder* default_set(int p0, int p1) { > return VirtualReturnValuePolicy::set(p0, p1); > } > > }; > > > }// namespace > > > // Module ====================================================================== > BOOST_PYTHON_MODULE(new_) > { > class_< NonVirtual, boost::noncopyable >("NonVirtual", no_init) > .def_readwrite("name", &NonVirtual::name) > .def_readwrite("size", &NonVirtual::size) > .def_readwrite("width", &NonVirtual::width) > .def("set", &NonVirtual::set, NonVirtual_set_overloads_1_3()) > ; > > class_< VirtualNonCopyable_Wrapper, boost::noncopyable >("VirtualNonCopyable", init< >()) > .def("set", VirtualNonCopyable_Wrapper::default_set_1) > .def("set", VirtualNonCopyable_Wrapper::default_set_2) > .def("set", &VirtualNonCopyable::set, &VirtualNonCopyable_Wrapper::default_set) > .def_readwrite("name", &VirtualNonCopyable::name) > .def_readwrite("size", &VirtualNonCopyable::size) > .def_readwrite("width", &VirtualNonCopyable::width) > ; > > class_< ValueHolder, boost::noncopyable >("ValueHolder", init< >()) > .def_readwrite("name", &ValueHolder::name) > ; > > def("getVirtualNonCopyable", &getVirtualNonCopyable, return_value_policy< reference_existing_object >()); > class_< NonVirtualReturnValuePolicy, boost::noncopyable >("NonVirtualReturnValuePolicy", init< >()) > .def_readwrite("name", &NonVirtualReturnValuePolicy::name) > .def_readwrite("size", &NonVirtualReturnValuePolicy::size) > .def_readwrite("width", &NonVirtualReturnValuePolicy::width) > .def("set", &NonVirtualReturnValuePolicy::set, NonVirtualReturnValuePolicy_set_overloads_1_3()[ return_internal_reference< 1 >() ]) > ; > > class_< VirtualReturnValuePolicy_Wrapper, boost::noncopyable >("VirtualReturnValuePolicy", init< >()) > .def("set", (ValueHolder* (*)( VirtualReturnValuePolicy &, const std::string&))VirtualReturnValuePolicy_Wrapper::default_set_1, return_internal_reference< 1 >()) > .def("set", (ValueHolder* (*)( VirtualReturnValuePolicy &, const std::string&, int))VirtualReturnValuePolicy_Wrapper::default_set_2, return_internal_reference< 1 >()) > .def("set", (ValueHolder* (VirtualReturnValuePolicy::*)(const std::string&, int, int) )&VirtualReturnValuePolicy::set, (ValueHolder* (VirtualReturnValuePolicy_Wrapper::*)(const std::string&, int, int))&VirtualReturnValuePolicy_Wrapper::default_set, return_internal_reference< 1 >()) > .def("set", (ValueHolder* (*)( VirtualReturnValuePolicy &))VirtualReturnValuePolicy_Wrapper::default_set_0, return_internal_reference< 1 >()) > .def("set", (ValueHolder* (*)( VirtualReturnValuePolicy &, int))VirtualReturnValuePolicy_Wrapper::default_set_1, return_internal_reference< 1 >()) > .def("set", (ValueHolder* (VirtualReturnValuePolicy::*)(int, int) )&VirtualReturnValuePolicy::set, (ValueHolder* (VirtualReturnValuePolicy_Wrapper::*)(int, int))&VirtualReturnValuePolicy_Wrapper::default_set, return_internal_reference< 1 >()) > .def_readwrite("name", &VirtualReturnValuePolicy::name) > .def_readwrite("size", &VirtualReturnValuePolicy::size) > .def_readwrite("width", &VirtualReturnValuePolicy::width) > ; > > def("getVirtualReturnValuePolicy", &getVirtualReturnValuePolicy, return_value_policy< reference_existing_object >()); > } > > ---------------------------------------------------------------------------- ---- > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: error.txt URL: From bernhardprivat at realspace.org Tue Jan 4 21:45:10 2005 From: bernhardprivat at realspace.org (=?ISO-8859-1?Q?Bernhard_Gl=FCck?=) Date: Tue, 04 Jan 2005 21:45:10 +0100 Subject: [C++-sig] Boost::python and shared_ptr Message-ID: Hi ! I am using a boost::python to script our newest project. We use boost::shared_ptr for almost all of our objects. How do i correctly wrap my classes so that they are held as shared_ptr objects and passed around that way ? I tried doing it like it was posted this mailing list before, but with the following problems. My environment is as follows:: Python 2.4, Boost 1.32.0 Compiler: VC7.1 Here the relevant code passages: First our game object which holds smart pointers to several sub systems: typedef boost::shared_ptr< class GraphicsServer > GraphicsServerPtr; typedef boost::shared_ptr< class AudioServer > AudioServerPtr; typedef boost::shared_ptr< class ScriptServer > ScriptServerPtr; typedef boost::shared_ptr< class InputServer > InputServerPtr; typedef boost::shared_ptr< class PhysicsServer > PhysicsServerPtr; typedef boost::shared_ptr< class AiServer > AiServerPtr; typedef boost::shared_ptr< class ConfigurationServer > ConfigurationServerPtr; typedef boost::shared_ptr< class TimeServer > TimeServerPtr; class Game : public Ogre::Singleton, public Ogre::FrameListener { public: const GraphicsServerPtr & GetGraphicsServer() const; const AudioServerPtr & GetAudioServer() const; const ScriptServerPtr & GetScriptServer() const; const InputServerPtr & GetInputServer() const; const PhysicsServerPtr & GetPhysicsServer() const; const AiServerPtr & GetAiServer() const; const ConfigurationServerPtr & GetConfigurationServer() const; const TimeServerPtr & GetTimeServer() const; void Start(); void Stop(); bool frameStarted(const Ogre::FrameEvent& evt); bool frameEnded( const Ogre::FrameEvent & evt); Game(); virtual ~Game(); private: GraphicsServerPtr mGraphicsServer; AudioServerPtr mAudioServer; ScriptServerPtr mScriptServer; InputServerPtr mInputServer; PhysicsServerPtr mPhysicsServer; AiServerPtr mAiServer; ConfigurationServerPtr mConfigurationServer; TimeServerPtr mTimeServer; bool mStop; }; Now our configuration server code that stores "registry" style values ( configuration information for our game ) class ConfigurationServer : public Server { public: template inline T GetValue( const std::string & name,T defaultValue ) { if ( mValues.find(name) != mValues.end() ) { boost::any value = mValues[name]; if ( value.type() == typeid(T )) { return boost::any_cast(value); } else { boost::format errorFmt("Configuration value (%1%) of wrong type (%2%), expected (%3%), using default of (%4%)."); errorFmt % name; errorFmt % value.type().name(); errorFmt % typeid(T).name(); errorFmt % defaultValue; Log( errorFmt.str() ); } } else { boost::format errorFmt("Configuration value (%1%) not found, using default of (%2%)."); errorFmt % name; errorFmt % defaultValue; Log( errorFmt.str() ); } return defaultValue; } template inline void SetValue( const std::string & name,T value ) { mValues[name] = boost::any(value); } virtual bool Reset(); virtual bool Initialize(); virtual bool Shutdown(); virtual bool Update( float deltaTime ); ConfigurationServer(); virtual ~ConfigurationServer(); private: std::map mValues; }; And now the export part: /////////////////////////////////////////////////////////// void PyExportConfigurationServer() { Log("Exported configuration server."); void (ConfigurationServer::*cm1)( const std::string &,int ) = &ConfigurationServer::SetValue; void (ConfigurationServer::*cm2)( const std::string &,float)=&ConfigurationServer::SetValue; void (ConfigurationServer::*cm3)( const std::string &,bool ) =&ConfigurationServer::SetValue; void (ConfigurationServer::*cm4)( const std::string &,std::string ) =&ConfigurationServer::SetValue; register_ptr_to_python< boost::shared_ptr >(); class_< ConfigurationServer,boost::shared_ptr > ("ConfigurationServer",no_init ) .def("set",cm1) .def("set",cm2) .def("set",cm3) .def("set",cm4); } /////////////////////////////////////////////////////////// void PyExportGame() { DeepVoid::Log("Exported game."); class_ ("Game",no_init ) .def("quit",&Game::Stop ) .def("getConfigurationServer",&Game::GetConfigurationServer, return_value_policy()); def("getGame",&Game::getSingleton, return_value_policy()); } /////////////////////////////////////////////////////////// BOOST_PYTHON_MODULE(dv) { PyExportConfigurationServer(); PyExportGame(); } The problem now is that the game class works as expected but whenever i do something like this: import dv game = dv.getGame() config = game.getConfigurationServer() config.set("Graphics.Fullscreen",1) I get the following error: exceptions.TypeError 20:54:20: No Python class registered for C++ class class boost::shared_ptr 20:54:20: File "DeepVoidConfig.py", line 3, in ? config = game.getConfigurationServer() I have no clue why this could happen. I tried chaning the export code for the ConfiguratioNServer in various ways ( leaving out register_ptr_to_python, or the second wrapper definition ) to no avail.. Both classes get exported by the way ( as my log tells me, thats why i have those two Log statements in the code ).... So what can i do to pass around my objects as shared_ptrs ? Ideally i would like almost all objects of our engine to be held in shared_ptr instead of normal ones. Hope anyone can help :-) Thanks in advance Bernhard Gl?ck From dave at boost-consulting.com Wed Jan 5 00:11:52 2005 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 04 Jan 2005 18:11:52 -0500 Subject: [C++-sig] Re: Boost::python and shared_ptr In-Reply-To: References: Message-ID: Bernhard Gl?ck wrote: > Hi ! > > I am using a boost::python to script our newest project. > We use boost::shared_ptr for almost all of our objects. > > How do i correctly wrap my classes so that they are held as shared_ptr > objects and > passed around that way ? I tried doing it like it was posted this > mailing list > before, but with the following problems. > > My environment is as follows:: > > Python 2.4, > Boost 1.32.0 > Compiler: VC7.1 > > Here the relevant code passages: > > First our game object which holds smart pointers to several sub systems: Please try to cut down your examples to something more manageable in the future, if possible. > register_ptr_to_python< boost::shared_ptr >(); > > class_< ConfigurationServer,boost::shared_ptr > > ("ConfigurationServer",no_init ) You don't need both of these. The to-python conversion for boost::shared_ptr is automatically registered by the class_<...> declaration. > The problem now is that the game class works as expected but whenever i do > something like this: > > import dv > game = dv.getGame() > config = game.getConfigurationServer() > config.set("Graphics.Fullscreen",1) > > I get the following error: > > exceptions.TypeError > 20:54:20: No Python class registered for C++ class class > boost::shared_ptr DeepVoid::ConfigurationServer> > 20:54:20: File "DeepVoidConfig.py", line 3, in ? config = > game.getConfigurationServer() All I can guess is that PyExportConfigurationServer hasn't been executed yet. Try setting a breakpoint there. > I have no clue why this could happen. I tried chaning the export code > for the > ConfiguratioNServer in various ways ( leaving out register_ptr_to_python, > or the second wrapper definition ) to no avail.. > > Both classes get exported by the way ( as my log tells me, thats why i have > those two Log statements in the code ).... Oh. Hm. Err.... why are you using this return value policy? .def("getConfigurationServer",&Game::GetConfigurationServer, return_value_policy()); That's your problem. I suggest you go back and review the meaning of these policies, and post any questions you have to this list to make sure you understand them. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From dave at boost-consulting.com Wed Jan 5 00:42:40 2005 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 04 Jan 2005 18:42:40 -0500 Subject: [C++-sig] Re: ANN: Fusion v0.2, C++ integration for Twisted In-Reply-To: <1103844768.14088.138.camel@sheriffpony> References: <1103844768.14088.138.camel@sheriffpony> Message-ID: <41DB29F0.10805@boost-consulting.com> Itamar Shtull-Trauring wrote: > Fusion is a library that supports implementing protocols in C++ for use > with Twisted, allowing control over memory allocation strategies, fast > method calls internally, etc.. Fusion supports TCP, UDP and multicast, > and is implemented using the Boost.Python python bindings. Hey, cool! I'll add it to the Boost.Python projects page! -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From dave at boost-consulting.com Wed Jan 5 00:42:40 2005 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 04 Jan 2005 18:42:40 -0500 Subject: [C++-sig] Re: ANN: Fusion v0.2, C++ integration for Twisted In-Reply-To: <1103844768.14088.138.camel@sheriffpony> References: <1103844768.14088.138.camel@sheriffpony> Message-ID: <41DB29F0.10805@boost-consulting.com> Itamar Shtull-Trauring wrote: > Fusion is a library that supports implementing protocols in C++ for use > with Twisted, allowing control over memory allocation strategies, fast > method calls internally, etc.. Fusion supports TCP, UDP and multicast, > and is implemented using the Boost.Python python bindings. Hey, cool! I'll add it to the Boost.Python projects page! -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From gaiacrtn at free.fr Fri Jan 7 18:24:49 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Fri, 7 Jan 2005 18:24:49 +0100 Subject: [C++-sig] boost.python: problem exposing static attribute with specific to_python converter Message-ID: <02a001c4f4dd$cab31420$0200a8c0@lain> I'm trying to expose 'staticVar' in the following class: struct TestString { static CEGUI::String staticVar; CEGUI::String memberFn() const { return CEGUI::String( "member" ); } }; CEGUI::String has no relation with std::string, except that you can construct CEGUI::String implicitly with an std::string. A specific to_python converter is used to expose it (see below). CEGUI::String and TestString are exposed as follow: struct CEGUIStringToPython { static PyObject *convert( const CEGUI::String &s ) { return PyString_FromString( s.c_str() ); } }; void registerCEGUIStringConversion() { boost::python::to_python_converter(); boost::python::implicitly_convertible(); boost::python::class_( "TestString", boost::python::init<>() ) .def_readonly( "staticVar", &TestString::staticVar ) .def( "memberFn", &TestString::memberFn ) ; } But when running the test below, calling memberFn() works, but staticVar fails. Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import localcegui as cegui >>> print "Member:", cegui.TestString().memberFn() Member: member >>> print "StaticVar:", cegui.TestString.staticVar StaticVar: Traceback (most recent call last): File "", line 1, in ? TypeError: No Python class registered for C++ class class CEGUI::String Changing 'staticVar' type from CEGUI::String to std::string remove this error message, so something is really going on with the to_python conversion. Why isn't the to_python_converter found ? Any help is welcome, Baptiste. From greg.landrum at gmail.com Fri Jan 7 23:56:55 2005 From: greg.landrum at gmail.com (Greg Landrum) Date: Fri, 7 Jan 2005 14:56:55 -0800 Subject: [C++-sig] using shared_ptrs with the vector_indexing_suite Message-ID: <60825b0f05010714564d71e769@mail.gmail.com> I'm attempting to get shared_ptrs working in combination with the vector_indexing_suite in order to make it easy to return std::vectors of shared_ptrs from our code. I feel like I've got a reasonable grasp of what's required to return shared_ptrs (given how easy that is now, this isn't much of an accomplishment), and I've even managed to get them working with the iterator interface, but the combination with vector_indexing_suite eludes me. The attached module and testing code demonstrate the problem. When I build this module and run the test (linux, python 2.3.4, g++ 3.2, boost 1.32), all the tests pass except for test5 and test5b, which use std::vectors of shared_ptrs. Both of those tests fail with the error: TypeError: No Python class registered for C++ class boost::shared_ptr Because the basic shared_ptr operations and the more complicated iterator stuff work, I'm guessing this has something to do with the vector_indexing_suite itself. Thanks in advance for any help, -greg -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: module.cpp URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: test.py Type: text/x-python Size: 1321 bytes Desc: not available URL: From dave at boost-consulting.com Sat Jan 8 00:18:59 2005 From: dave at boost-consulting.com (David Abrahams) Date: Fri, 07 Jan 2005 18:18:59 -0500 Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter In-Reply-To: <02a001c4f4dd$cab31420$0200a8c0@lain> References: <02a001c4f4dd$cab31420$0200a8c0@lain> Message-ID: Baptiste Lepilleur wrote: > Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on > win32 > Type "help", "copyright", "credits" or "license" for more information. >>>> import localcegui as cegui >>>> print "Member:", cegui.TestString().memberFn() > Member: member >>>> print "StaticVar:", cegui.TestString.staticVar > StaticVar: > Traceback (most recent call last): > File "", line 1, in ? > TypeError: No Python class registered for C++ class class CEGUI::String > > Changing 'staticVar' type from CEGUI::String to std::string remove this > error message, so something is really going on with the to_python > conversion. Why isn't the to_python_converter found ? According to http://www.boost.org/libs/python/doc/v2/class.html#class_-spec-modifiers def_readonly(name, pointer_to_data) is equivalent to this->add_static_property(name, make_getter(pointer_to_data)); (modulo a typo, which I'm fixing now). and according to http://www.boost.org/libs/python/doc/v2/data_members.html#make_getter-spec make_getter(pointer_to_data) "Creates a Python callable object which accepts no arguments and returns [pointer_to_data] ... converted to_python on demand. If policies is supplied, it will be applied to the function as described here. Otherwise, the library attempts to determine whether D is a user-defined class type, and if so uses reference_existing_object." reference_existing_object requires a Python wrapper class for the returned type to exist, so that it can create an instance of that class containing a pointer to the pointee. If you want it to use your converter, you need to get it to use some other policy, like default_call_polices: .add_static_property("staticVar", make_getter(&TestString::staticVar, default_call_policies())); HTH, -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From gmeeker at ilm.com Sat Jan 8 01:12:34 2005 From: gmeeker at ilm.com (Garrick Meeker) Date: Fri, 07 Jan 2005 16:12:34 -0800 Subject: [C++-sig] Python exceptions Message-ID: <41DF2572.1060003@ilm.com> I'm porting some old code to boost. I have a function that returns a PyObject* and if an error occurs it calls PyErr_SetString(PyExc_AttributeError, "...") and returns NULL. No C++ exceptions are involved. With boost, however, the NULL is converted to None. How can I generate an AttributeError exception? All I see from the docs is that I could define a new class, call register_exception_translator(), and throw this class. Since I'm not dealing with existing exception classes, is there a simpler, built-in way? Something like: throw boost::python::exception(PyExc_AttributeError, "error string"); From jbrandmeyer at earthlink.net Sat Jan 8 01:35:27 2005 From: jbrandmeyer at earthlink.net (Jonathan Brandmeyer) Date: Fri, 07 Jan 2005 19:35:27 -0500 Subject: [C++-sig] Python exceptions In-Reply-To: <41DF2572.1060003@ilm.com> References: <41DF2572.1060003@ilm.com> Message-ID: <1105144528.7894.10.camel@illuvatar> On Fri, 2005-01-07 at 16:12 -0800, Garrick Meeker wrote: > I'm porting some old code to boost. I have a function that returns a > PyObject* and if an error occurs it calls > PyErr_SetString(PyExc_AttributeError, "...") and returns NULL. No C++ > exceptions are involved. With boost, however, the NULL is converted to > None. > > How can I generate an AttributeError exception? All I see from the docs > is that I could define a new class, call > register_exception_translator(), and throw this class. Since I'm not > dealing with existing exception classes, is there a simpler, built-in > way? Something like: > > throw boost::python::exception(PyExc_AttributeError, "error string"); > See: http://www.boost.org/libs/python/doc/v2/errors.htm -Jonathan From dave at boost-consulting.com Sat Jan 8 03:10:32 2005 From: dave at boost-consulting.com (David Abrahams) Date: Fri, 07 Jan 2005 21:10:32 -0500 Subject: [C++-sig] Re: Python exceptions In-Reply-To: <1105144528.7894.10.camel@illuvatar> References: <41DF2572.1060003@ilm.com> <1105144528.7894.10.camel@illuvatar> Message-ID: Jonathan Brandmeyer wrote: > On Fri, 2005-01-07 at 16:12 -0800, Garrick Meeker wrote: >> I'm porting some old code to boost. I have a function that returns a >> PyObject* and if an error occurs it calls >> PyErr_SetString(PyExc_AttributeError, "...") and returns NULL. No C++ >> exceptions are involved. With boost, however, the NULL is converted to >> None. >> >> How can I generate an AttributeError exception? All I see from the docs >> is that I could define a new class, call >> register_exception_translator(), and throw this class. Since I'm not >> dealing with existing exception classes, is there a simpler, built-in >> way? Something like: >> >> throw boost::python::exception(PyExc_AttributeError, "error string"); >> > > > See: http://www.boost.org/libs/python/doc/v2/errors.htm http://www.boost.org/libs/python/doc/v2/errors.html ^ ? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From gaiacrtn at free.fr Sat Jan 8 11:33:59 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Sat, 8 Jan 2005 11:33:59 +0100 Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter References: <02a001c4f4dd$cab31420$0200a8c0@lain> Message-ID: <02b601c4f56d$9080b150$0200a8c0@lain> ----- Original Message ----- From: "David Abrahams" To: Sent: Saturday, January 08, 2005 12:18 AM Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter > Baptiste Lepilleur wrote: > > > Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on > > win32 > > Type "help", "copyright", "credits" or "license" for more information. > >>>> import localcegui as cegui > >>>> print "Member:", cegui.TestString().memberFn() > > Member: member > >>>> print "StaticVar:", cegui.TestString.staticVar > > StaticVar: > > Traceback (most recent call last): > > File "", line 1, in ? > > TypeError: No Python class registered for C++ class class CEGUI::String > > > > Changing 'staticVar' type from CEGUI::String to std::string remove this > > error message, so something is really going on with the to_python > > conversion. Why isn't the to_python_converter found ? > [...] > reference_existing_object requires a Python wrapper class for the > returned type to exist, so that it can create an instance of that class > containing a pointer to the pointee. If you want it to use your > converter, you need to get it to use some other policy, like > default_call_polices: > > .add_static_property("staticVar", make_getter(&TestString::staticVar, > default_call_policies())); Thanks, this explains clearly what's going on. I couldn't get the above solution to work directly. I believe 'CEGUI::String &' is deduced as a return type instead of 'CEGUI::String'. Here a simplified compilation error stack (I'm using boost 1.32 & VC++ 7.1): include\boost\python\detail\caller.hpp(199) : error C2027: use of undefined type 'boost::python::detail::specify_a_retur n_value_policy_to_wrap_functions_returning' with [ T=result_t ] //... include\boost\python\data_members.hpp(167) : see reference to function template instantiation 'boost::python::ap i::object boost::python::make_function,Policies,boo st::mpl::vector1>(F,const Call Policies &,const KeywordsOrSignature &)' being compiled with [ Data=CEGUI::String, Policies=boost::python::default_call_policies, T0=CEGUI::String &, F=boost::python::detail::datum, CallPolicies=boost::python::default_call_policies, KeywordsOrSignature=boost::mpl::vector1 ] //... src\pycegui\CEGUIStringWrapper.h(32) : see reference to function template instantiation 'boost::python::api::obj ect boost::python::make_getter(const D & ,const Policies &)' being compiled with [ D=CEGUI::String *, Policies=boost::python::default_call_policies ] Is this a bug ? I got it working using: .add_static_property( "staticVar", make_getter(&TestString::staticVar, return_value_policy() ) ) Is there a way to change the return type used in the function generated by make_getter to be by value instead of by reference, so that the default_call_policies could be used ? Thanks for your help, Baptiste. From dave at boost-consulting.com Sat Jan 8 17:25:38 2005 From: dave at boost-consulting.com (David Abrahams) Date: Sat, 08 Jan 2005 11:25:38 -0500 Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter In-Reply-To: <02b601c4f56d$9080b150$0200a8c0@lain> References: <02a001c4f4dd$cab31420$0200a8c0@lain> <02b601c4f56d$9080b150$0200a8c0@lain> Message-ID: Baptiste Lepilleur wrote: > Is this a bug ? No, just bad instructions from me. Clearly the docs don't give all the information neccessary to get it right or I would have given you good instructions :( > I got it working using: > .add_static_property( "staticVar", > make_getter(&TestString::staticVar, > return_value_policy() ) ) > > Is there a way to change the return type used in the function generated > by make_getter to be by value instead of by reference, so that the > default_call_policies could be used ? No, but of course you can always make your own getter function that returns by value. It's hard to say which would be preferable. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com From gaiacrtn at free.fr Sun Jan 9 21:22:48 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Sun, 9 Jan 2005 21:22:48 +0100 Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter References: <02a001c4f4dd$cab31420$0200a8c0@lain> <02b601c4f56d$9080b150$0200a8c0@lain> Message-ID: <034101c4f688$fd56dd10$0200a8c0@lain> ----- Original Message ----- From: "David Abrahams" To: Sent: Saturday, January 08, 2005 5:25 PM Subject: [C++-sig] Re: boost.python: problem exposing static attribute with specific to_python converter > Baptiste Lepilleur wrote: > > > Is this a bug ? > > No, just bad instructions from me. Clearly the docs don't give all the > information neccessary to get it right or I would have given you good > instructions :( > > > I got it working using: > > .add_static_property( "staticVar", > > make_getter(&TestString::staticVar, > > return_value_policy() ) ) > > > > Is there a way to change the return type used in the function generated > > by make_getter to be by value instead of by reference, so that the > > default_call_policies could be used ? > > No, but of course you can always make your own getter function that > returns by value. It's hard to say which would be preferable. Well, I'll just enhance pyste to support policy for class attribute as it is anyway equivalent to making my one getter. Thanks for helping, Baptiste. From daniel at wand.net.nz Wed Jan 12 10:40:59 2005 From: daniel at wand.net.nz (Daniel Lawson) Date: Wed, 12 Jan 2005 22:40:59 +1300 Subject: [C++-sig] embedding an extended python module Message-ID: <41E4F0AB.7090702@wand.net.nz> Hi there, I'm using Boost:Python to extend Python, in order to provide access to some C++ classes I have written. This is working fine - I can load the resulting module in Python, instantiate the classes exported via Boost, and manipulate them and so on. typedef std::map attrmap; class Node { std::string name; attrmap attrs; public: Node(std::string name); ~Node(); void addAttr(std::string key, int val); void getAttr(std::string key); } BOOST_PYTHON_MODULE(Node) { using namespace boost::python; class_("Node",init()) .def("addAttr", &Node::addAttr) .def("getAttr", &Node::getAttr) ; } I also have a program which has embedded Python in it. This program can be passed the names of some python files, which it will load and import specific symbols from: filtername = "filter.py"; pName = PyString_FromString(filtermod); pfilterhnd = PyImport_Import(pName); pDict = PyModule_GetDict(pfilterhnd); pfilter = PyDict_GetItemString(pDict, "filter"); And so on. Later on, I then call this filter function: pName = PyString_FromString("name"); pNode = PyString_FromString("node"); pArgs = PyTuple_New(2); PyTuple_SetItem(pArgs, 0, pName); PyTuple_SetItem(pArgs, 1, pNode); pRetVal = PyObject_CallObject(phandler,pArgs); ... Where pArgs is a tuple of arguments. This works fine, as long as I only pass basic Python types to the function - eg, strings (PyString_FromString), longs (PyInt_FromLong) etc. However, I want to be able to pass, into the embedded python, instances (pointers to, actually) the classes which I have exported via Boost. More so, I want the python module I loaded above to be able to modify the datastructure, and have the calling program make use of this. I've imported the appropriate modules into the python interpreter embedded into my C++ program. From what I've read, within the calling C++ program I need to convert (or wrap) the instance of my Node class into a PyObject *. Once I've done that, I can use PyObject_Callfunction or similar to call the python function, passing my Node class into it. Once in there, python will use the boost-extended module to access it. I've been reading mailing lists all day, it seems like this should be very possible, I'm just totally stumped as to how. There's plenty of examples for embedding python into a C/C++ program, and there's plenty of examples for extending python with a C/C++ extension, but there don't seem to be so many which put the two together. Thanks, Daniel From iluetkeb at gmail.com Wed Jan 12 15:47:55 2005 From: iluetkeb at gmail.com (=?ISO-8859-1?Q?Ingo_L=FCtkebohle?=) Date: Wed, 12 Jan 2005 15:47:55 +0100 Subject: [C++-sig] embedding an extended python module In-Reply-To: <41E4F0AB.7090702@wand.net.nz> References: <41E4F0AB.7090702@wand.net.nz> Message-ID: Using a PyObject: #include ... call(pyobject, args) Or wrap your PyObject as an object (http://www.boost.org/libs/python/doc/tutorial/doc/html/python/embedding.html) and invoke it as a callable. Ingo From daniel at wand.net.nz Wed Jan 12 23:51:44 2005 From: daniel at wand.net.nz (Daniel Lawson) Date: Thu, 13 Jan 2005 11:51:44 +1300 Subject: [C++-sig] embedding an extended python module In-Reply-To: References: <41E4F0AB.7090702@wand.net.nz> Message-ID: <41E5AA00.8020108@wand.net.nz> Ingo L?tkebohle wrote: >Using a PyObject: > > #include > ... > call(pyobject, args) > >Or wrap your PyObject as an object >(http://www.boost.org/libs/python/doc/tutorial/doc/html/python/embedding.html) >and invoke it as a callable. > > I understand that. However, within my calling program (the one embedding python), I don't have a PyObject yet. I have a pointer to a C++ class. This class has been exported via boost. I guess I'm missing something fundamental, like that boost provides a PyObject * pointer within a boost-wrapped class. Any pointers? To clarify: Node *testnode = new Node("test") filtername = "filter.py"; pName = PyString_FromString(filtername); pfilterhnd = PyImport_Import(pName); pDict = PyModule_GetDict(pfilterhnd); // this is the function we wish to call // it accepts a "Node" parameter, and returns an int pfilter = PyDict_GetItemString(pDict, "filter"); So, you're suggesting I can do something like: boost::python::call(pFilter, testnode) And boost will handle the conversion? Thanks, Daniel From rwgk at yahoo.com Thu Jan 13 00:45:53 2005 From: rwgk at yahoo.com (Ralf W. Grosse-Kunstleve) Date: Wed, 12 Jan 2005 15:45:53 -0800 (PST) Subject: [C++-sig] embedding an extended python module In-Reply-To: <41E5AA00.8020108@wand.net.nz> Message-ID: <20050112234553.94607.qmail@web20228.mail.yahoo.com> --- Daniel Lawson wrote: > I understand that. However, within my calling program (the one embedding > python), I don't have a PyObject yet. I have a pointer to a C++ class. > This class has been exported via boost. Maybe you just want to say boost::python::object(cpp_instance) or something like boost::python::object(boost::python::ptr(cpp_pointer)) ? I am not sure about the second form since I never use raw pointers. If this is on the right track I hope David will help out with the exact details. __________________________________ Do you Yahoo!? Yahoo! Mail - You care about security. So do we. http://promotions.yahoo.com/new_mail From wbruna at yahoo.com Sun Jan 16 05:23:34 2005 From: wbruna at yahoo.com (Wagner Bruna) Date: Sat, 15 Jan 2005 20:23:34 -0800 (PST) Subject: [C++-sig] Wrapping functions with lvalue arguments Message-ID: <20050116042334.31081.qmail@web13603.mail.yahoo.com> Hello, I'm trying to wrap some C++ functions that take some arguments by non-const reference. I didn't want to return a tuple in this particular case (mainly because there'll be a lot of variables), so I tried to build a "holder" object to store the primitive type and pass it as an lvalue. Something like: void my_function(int & value); struct IntHolder { int obj; operator int&() { return obj; } }; (in theory, the implicit conversion would allow me to wrap and use my_function directly) But I couldn't find a way to wrap the conversion operator to int&. I also tried a free function returning int&, and a wrapped int member, without sucess. What I found really strange was, although I could wrap my_function(int&) without problems, I couldn't find any way to actually pass an lvalue int into it. Well... The curious part is: after some unfruitful tries, almost by accident I found a rather bizarre way. Easier to show than to describe: #include #include #include int my_function(int & i) { return i++; } // "member" functions int get_obj(int obj) { return obj; } void set_obj(int & obj, int v) { obj = v; } BOOST_PYTHON_MODULE(holder) { using namespace boost::python; def("my_function", &my_function); class_("IntHolder", init()) .add_property("obj", &get_obj, &set_obj) ; } It is necessary to comment out the is_class static assertion on boost/python/object/make_instance.hpp - and I understand this implies I'm *not* doing something recommended... anyways, it did the job: >>> from holder import * >>> a = IntHolder(42) >>> a >>> a.obj 42 >>> my_function(a) 42 >>> a.obj 43 But is there a better (or "less hacking") way to make this "holder" object? And are there better alternatives to deal with functions that must return by reference? Thanks in advance, Wagner pdf: FWIW, I'm using Boost.Python from release 1.32.0, and Visual C++ 6. __________________________________ Do you Yahoo!? Yahoo! Mail - Helps protect you from nasty viruses. http://promotions.yahoo.com/new_mail From gaiacrtn at free.fr Sun Jan 16 09:29:59 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Sun, 16 Jan 2005 09:29:59 +0100 Subject: [C++-sig] Wrapping functions with lvalue arguments References: <20050116042334.31081.qmail@web13603.mail.yahoo.com> Message-ID: <053901c4fba5$911032b0$0200a8c0@lain> I believe boost::python::implicitly_convertible<...>() is what you are looking for. Check the reference doc, it has a example very similar to you case. Baptiste. ----- Original Message ----- From: "Wagner Bruna" To: Sent: Sunday, January 16, 2005 5:23 AM Subject: [C++-sig] Wrapping functions with lvalue arguments > Hello, > > I'm trying to wrap some C++ functions that take some > arguments by non-const reference. I didn't want to > return a tuple in this particular case (mainly because > there'll be a lot of variables), so I tried to build a > "holder" object to store the primitive type and pass > it as an lvalue. Something like: > > void my_function(int & value); > > struct IntHolder { > int obj; > operator int&() { > return obj; > } > }; > > (in theory, the implicit conversion would allow me to > wrap and use my_function directly) > > But I couldn't find a way to wrap the conversion > operator to int&. I also tried a free function > returning int&, and a wrapped int member, without > sucess. What I found really strange was, although I > could wrap my_function(int&) without problems, I > couldn't find any way to actually pass an lvalue int > into it. > > [...] > > But is there a better (or "less hacking") way to make > this "holder" object? And are there better > alternatives to deal with functions that must return > by reference? > > Thanks in advance, > Wagner > > pdf: FWIW, I'm using Boost.Python from release 1.32.0, > and Visual C++ 6. From gaiacrtn at free.fr Tue Jan 18 10:22:33 2005 From: gaiacrtn at free.fr (Baptiste Lepilleur) Date: Tue, 18 Jan 2005 10:22:33 +0100 Subject: [C++-sig] boost.python, how to have python transfer ownership to a c++ object Message-ID: <001e01c4fd3f$3ec52150$0200a8c0@lain> I'm trying to expose a method that take ownership of the passed parameter (as if the parameter was an auto_ptr): --- struct Item { // polymorphic class (may be subclassed) }; struct ListBox { void addItem( Item *item ) // take ownship of 'item' { item_.reset( item ); } private: std::auto_ptr item_; }; --- And use it like this in python: class MyItem(Item): pass list = ListBox() list.addItem( MyItem() ) The issue is that the MyItem instance is owned by python and get destroyed by python after the addItem statement. How can I indicate that the 'item' parameter passed to addItem() is now owned by the C++ instance of 'list' ? Baptiste. From wbruna at yahoo.com Wed Jan 19 00:16:11 2005 From: wbruna at yahoo.com (Wagner Bruna) Date: Tue, 18 Jan 2005 15:16:11 -0800 (PST) Subject: [C++-sig] Re: Wrapping functions with lvalue arguments In-Reply-To: <20050116110006.926AE1E401A@bag.python.org> Message-ID: <20050118231611.2174.qmail@web13608.mail.yahoo.com> Hi, "Baptiste Lepilleur" wrote: > I believe > boost::python::implicitly_convertible<...>() is what > you are looking for. Check the reference doc, it has > a example very similar to you case. Thanks for your reply, but it didn't work. Looks like implicitly_convertible should not be used for references (at least to int): boost/python/converter/implicit.hpp(33) : error C2464: 'int &' : cannot use 'new' to allocate a reference (...) while compiling class-template member function 'void __cdecl boost::python::converter::implicit:: construct(struct _object *, struct boost::python::converter::rvalue_from_python_stage1_data *)' Well, I found another way. Even uglier than my first solution, but at least I'm not changing library headers anymore... Here it goes: int lvalue(int & i) { return i++; } struct IntHolder { int obj_; IntHolder(int obj) : obj_(obj) { } operator int&() { return obj_; } operator int() const { return obj_; } static int get(int obj) { return obj; } static void set(int & obj, int value) { obj = value; } }; namespace boost { namespace python { namespace detail { template <> inline typeinfo msvc_typeid(BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(IntHolder)) { return python::detail::msvc_typeid((boost::type*)0); } }}} BOOST_PYTHON_MODULE(holder) { using namespace boost::python; def("rvalue", &rvalue); class_("IntHolder", init()) .add_property("obj", &IntHolder::get, &IntHolder::set) ; } >>> a = IntHolder(0) >>> lvalue(a) 0 >>> a.obj 1 If I understand correctly, what I'm doing here is registering IntHolder with the int type identifier, so the type system matches my struct with the lvalue int parameter.Still a hack, though... By the way, wrapping a function returning int& using return_value_policy gets that same "is_class" assertion failure on object/make_instance.hpp. Maybe that's intentional - because Python integers are immutable. But then I don't understand why wrapping an int& parameter is accepted. Thanks, Wagner __________________________________ Do you Yahoo!? Yahoo! Mail - You care about security. So do we. http://promotions.yahoo.com/new_mail From gregsteele at speakeasy.net Wed Jan 19 07:36:38 2005 From: gregsteele at speakeasy.net (gregsteele at speakeasy.net) Date: Wed, 19 Jan 2005 06:36:38 +0000 Subject: [C++-sig] .def versus .add_property Message-ID: I want to add a accessor function to a python class, but give it member semantics. When I use .def to add the accessor, everything works fine. When I use .add_property, I get compiler errors w/ Visual C++ 7.1. I have included example code below. struct vec_t { int len; int * x; vec_t(int length) { len = length; x = (int *) malloc(length*sizeof(int)); } ~vec_t() { if (x) free(x); } int get_len() {return len;} }; struct outer { vec_t v; outer( int len ) : v(len) {} ~outer() {} vec_t & get_v() { return (v); } }; BOOST_PYTHON_MODULE(test_add_property) { class_("vec", no_init) .add_property("len", &vec_t::get_len ); ; class_("outer", init() ) // this works fine //.def("v", &outer::get_v, return_internal_reference<>() ) // this doesn't compile .add_property("v", &outer::get_v, return_internal_reference<>() ) ; } Thanks. Greg From rwgk at yahoo.com Wed Jan 19 11:04:43 2005 From: rwgk at yahoo.com (Ralf W. Grosse-Kunstleve) Date: Wed, 19 Jan 2005 02:04:43 -0800 (PST) Subject: [C++-sig] .def versus .add_property In-Reply-To: Message-ID: <20050119100443.7049.qmail@web20228.mail.yahoo.com> I think you are just missing make_getter(): .add_property("v", make_getter(&outer::get_v, return_internal_reference<>())) --- gregsteele at speakeasy.net wrote: > // this works fine > //.def("v", &outer::get_v, return_internal_reference<>() ) > > // this doesn't compile > .add_property("v", &outer::get_v, return_internal_reference<>() > ) __________________________________ Do you Yahoo!? Take Yahoo! Mail with you! Get it on your mobile phone. http://mobile.yahoo.com/maildemo From abentley at panoramicfeedback.com Thu Jan 20 17:02:27 2005 From: abentley at panoramicfeedback.com (Aaron Bentley) Date: Thu, 20 Jan 2005 11:02:27 -0500 Subject: [C++-sig] Taking ownership of a base pointer Message-ID: Hi all, I have some polymorphic code that wants to take ownership of a base pointer. I've successfully used std::auto_ptr, to take ownership, but it doesn't work for std::auto_ptr. I could always declare wrapper functions for every derived type, but is there a better way? Aaron -- Aaron Bentley Director of Technology Panometrics, Inc. From jbrandmeyer at earthlink.net Fri Jan 21 20:55:31 2005 From: jbrandmeyer at earthlink.net (Jonathan Brandmeyer) Date: Fri, 21 Jan 2005 14:55:31 -0500 Subject: [C++-sig] Docstrings for properties Message-ID: <1106337331.4093.15.camel@localhost> I have been working on implementing docstrings for properties in Boost.Python. My code for normal properties works fine, but the code for static properties does not. Here is one example of the code for creating a property with a docstring: void class_base::add_property( char const* name, object const& fget, char const* docstr) { object property( (python::detail::new_reference) PyObject_CallFunction( (PyObject*)&PyProperty_Type, "Osss", fget.ptr(), 0, 0, docstr)); this->setattr(name, property); } Which I believe is equivalent to: self[name] = property( fget, None, None, docstr) But, the same code does not work for the static properties, and I do not understand why. void class_base::add_static_property( char const* name, object const& fget, char const* docstr) { object property( (python::detail::new_reference) PyObject_CallFunction( static_data(), "Osss", fget.ptr(), 0, 0, docstr)); this->setattr(name, property); } I suppose it has something to do with the definition of Boost.Python.StaticProperty, but I do not how that class works well enough to debug the problem (what are tp_descr_get and tp_descr_set doing? Their responsibilities are not documented in the Python manual). The error is that the docstring (and deleter) arguments appear to be ignored entirely. Thanks, -Jonathan From jbrandmeyer at earthlink.net Sat Jan 22 22:45:37 2005 From: jbrandmeyer at earthlink.net (Jonathan Brandmeyer) Date: Sat, 22 Jan 2005 16:45:37 -0500 Subject: [C++-sig] Docstrings for properties In-Reply-To: <1106337331.4093.15.camel@localhost> References: <1106337331.4093.15.camel@localhost> Message-ID: <1106430337.16055.2.camel@illuvatar> On Fri, 2005-01-21 at 14:55 -0500, Jonathan Brandmeyer wrote: > I have been working on implementing docstrings for properties in > Boost.Python. My code for normal properties works fine, but the code > for static properties does not. I haven't managed to figure out how to get docstrings to work for static properties. Since I did get it working for instance properties, I went ahead and added code to CVS to support them. -Jonathan From pirx at cs.tu-berlin.de Sun Jan 23 00:44:36 2005 From: pirx at cs.tu-berlin.de (Andreas) Date: Sun, 23 Jan 2005 00:44:36 +0100 Subject: [C++-sig] newbie: create shared_ptr to self within python In-Reply-To: References: <002e01c4fa72$d7f3a060$1d02a8c0@wxp2000> <003301c4fa85$0c9d8260$1d02a8c0@wxp2000> Message-ID: <41F2E564.5060306@cs.tu-berlin.de> hello, I have a problem with conversion of python class instances to shared_ptr within python. I defined an abstract base class in c++ that is used in c++ and in embedded python. Only shared_ptr to the concrete instances should be useable. Thus the concrete classes have hidden ctor's. They must provide a factory method for creating. Copying of an object must be done using a clone method. In detail there are two problems: 1. Create a shared_ptr to a new class instance by using a class factory method 2. Clone a python class instance and return a shared_ptr to the new instance The example code: //in c++ class Base { public: virtual ~Base() {} virtual shared_ptr clone() const = 0; virtual std::string name() const = 0; protected: Base() {} }; void whoiam(shared_ptr pBase) { std::cout << pBase->name(); } //in this example there is no need for class DerivedA. That's only for // better explanation of the context described above. class DerivedA : public Base { public: static shared_ptr create(int n) { return shared_ptr(new DerivedA(n)); } virtual shared_ptr clone() const { return shared_ptr(new DerivedA(*this)); } virtual std::string name() const { return "derivedA"; } protected: DerivedA(int n) : _n(n) {} DerivedA(const DerivedA& other) : _n(other._n) {} private: int _n; }; //wrapping base struct BaseWrapper : public Base, wrapper { shared_ptr clone() const {return this->get_override("clone")();} std::string name() const { return this->get_override("name")(); } }; //export BOOST_PYTHON_MODULE(test) { def("whoiam", &whoiam); class_, noncopyable>("Base", no_init) .def("clone", pure_virtual(&Base::clone)) .def("name", pure_virtual(&Base::name)) ; } //in python from test import * class DerivedB(Base): def __init__(self, data): self.__data = data @staticmethod def create(data): return DerivedB(data) def copy(self): return self def name(self): return 'derivedB' b = DerivedB.create('somestring') whoiam(b) bCopied = b.copy() whoiam(bCopied) Here is the result of the interpreter for both whoiam lines: whoiam(b) Boost.Python.ArgumentError: Python argument types in whoiam(DerivedB) did not match C++ signature: whoiam(class boost::shared_ptr) How can i define/register an converter which does such an implicit conversion? (I'm using Boost 1.32.0, MSVC7.1 and Python 2.4) Thanks a lot for any help, andreas From seefeld at sympatico.ca Sun Jan 23 04:11:04 2005 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Sat, 22 Jan 2005 22:11:04 -0500 Subject: [C++-sig] error in argument conversion Message-ID: <41F315C8.3040406@sympatico.ca> I'v run into a runtime error which I found no explanation for. Here is what I'm doing in python: >>> type(ptree) >>> ptree.car() Traceback (most recent call last): File "", line 1, in ? Boost.Python.ArgumentError: Python argument types in List.car(List) did not match C++ signature: car(PTree::List*) >>> where 'PTree.List' is a python wrapper around my class, which I generate so: Node *car(List *l) { return l->car();} Node *cdr(List *l) { return l->cdr();} BOOST_PYTHON_MODULE(PTree) { bpl::class_, Node *, boost::noncopyable> node("Node", bpl::no_init); bpl::class_, List *, boost::noncopyable> list("List", bpl::no_init); list.def("car", car, bpl::return_value_policy()); list.def("cdr", cdr, bpl::return_value_policy()); ... I don't quite understand the text in the 'ArgumentError' exception. It suggests the python type 'List' couldn't be converted to the C++ type 'PTree::List*'. Is that interpretation correct ? If so, what possible reasons exist for the requested conversion to fail, given the above definition of the wrapper class ? Thanks, Stefan PS: the reason I expose raw pointers and use the above return value policy is that these PTree classes all use a garbage collector library. From seefeld at sympatico.ca Sun Jan 23 04:48:55 2005 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Sat, 22 Jan 2005 22:48:55 -0500 Subject: [C++-sig] error in argument conversion In-Reply-To: <41F315C8.3040406@sympatico.ca> References: <41F315C8.3040406@sympatico.ca> Message-ID: <41F31EA7.4040007@sympatico.ca> Stefan Seefeld wrote: > I don't quite understand the text in the 'ArgumentError' exception. This error seems to hint that my interpretation wasn't far off: Traceback (most recent call last): File "../../../../contrib/bpl/ptree.py", line 21, in ? ptree.accept(walker) TypeError: No to_python (by-value) converter found for C++ type: PTree::List Here I called a method 'accept' that is defined for List's base class 'Node'. Why does bpl want a 'by-value converter' for PTree::List ? Does this imply a copy-construction of an actual PTree::List instead of PTree::List * somewhere ? Thanks for any hints, Stefan From seefeld at sympatico.ca Sun Jan 23 05:07:00 2005 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Sat, 22 Jan 2005 23:07:00 -0500 Subject: [C++-sig] error in argument conversion In-Reply-To: <41F31EA7.4040007@sympatico.ca> References: <41F315C8.3040406@sympatico.ca> <41F31EA7.4040007@sympatico.ca> Message-ID: <41F322E4.2040208@sympatico.ca> Finally: The issue is related to the fact that the factory of the initial PTree.List object I encountered the exceptions on is implemented in a separate extension. I thus have one extension 'PTree.so' that provides the definitions of types 'Node' and 'List', and a 'Parser.so' extension that provides 'parse': PTree::Node *parse(std::string const &filename); ... BOOST_PYTHON_MODULE(Parser) { // The PTree module uses garbage collection so just ignore memory management, // at least for now. bpl::def("parse", parse, bpl::return_value_policy()); } As soon as I merge both into a single extension module everything works as expected. But when using separate modules 'Parser' and 'PTree' I run into problems with 'by-value' conversions for type PTree::List. What is going on here ? Thanks, Stefan From Benjamin_Schmeling at gmx.de Mon Jan 24 16:48:45 2005 From: Benjamin_Schmeling at gmx.de (Benjamin Schmeling) Date: Mon, 24 Jan 2005 16:48:45 +0100 Subject: [C++-sig] implicit conversion Message-ID: <41F518DD.9060007@gmx.de> Hi, I am working on exposing a bigint class to python. Now I've got the problem that methods which take an bigint as an parameter do not accept Python longs. For example: import _PythonLiDIA x=123L; c=_PythonLiDIA.bigint(); _PythonLiDIA.gcd(c,x); Traceback (most recent call last): File "test.py", line 132, in ? _PythonLiDIA.gcd(a,x); Boost.Python.ArgumentError: Python argument types in _PythonLiDIA.gcd(bigint, long) did not match C++ signature: gcd(LiDIA::bigint, LiDIA::bigint) I don't know how to achieve implicit conversion at this point, turning an long automatically into an bigint. The other way round, turning an bigint into long can be realized by defining __long__. Can someone help me please? Benjamin From abentley at panoramicfeedback.com Mon Jan 24 19:44:58 2005 From: abentley at panoramicfeedback.com (Aaron Bentley) Date: Mon, 24 Jan 2005 13:44:58 -0500 Subject: [C++-sig] virtual functions returning const char Message-ID: I've encountered a problem wrapping virtual functions that return const char *. I get ReferenceError: Attempt to return dangling pointer to object of type: c Here's my example code (adapted from the tutorial): struct Base { virtual const char * f(){return "fee";} }; struct BaseWrap: Base { BaseWrap(PyObject* self_) : self(self_){} const char *f() { return call_method(self, "f"); } const char *default_f() {return Base::f();} PyObject *self; }; const char *call_f(Base &b) { return b.f(); } And then in the BOOST_PYTHON_MODULE class_("Base") .def("f", &Base::f, &BaseWrap::default_f) ; def ("call_f", call_f); Finally, in Python: class Derived(Base): def f(self): return "foo" d = Derived() assert(d.f() == "foo") assert(call_f(d) == "foo") b = Base() assert(b.f() == "fee") assert(call_f(b) == "fee") assert(Base().f() == "fee") b = Base() #all lines except this one pass assert(call_f(b) == "fee") All assertions except the last one pass. That is they pass 1. If I'm calling from Python or 2. If the default virtual function is not invoked. But if I invoke the default virtual function from C++, I get the dangling pointer exception. I don't really understand the problem, since string literals like "fee" should have a permanent location in memory. Aaron -- Aaron Bentley Director of Technology Panometrics, Inc. From olivier.ravard at novagrid.com Tue Jan 25 10:27:54 2005 From: olivier.ravard at novagrid.com (Olivier Ravard) Date: Tue, 25 Jan 2005 10:27:54 +0100 Subject: [C++-sig] import function execution Message-ID: <005201c502c0$267f4ae0$3d521481@ravard> Hi, How to define a C++ function that will be executed automaticaly when the module is imported ? Thanks. O.R. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicodemus at esss.com.br Tue Jan 25 12:26:02 2005 From: nicodemus at esss.com.br (Nicodemus) Date: Tue, 25 Jan 2005 08:26:02 -0300 Subject: [C++-sig] import function execution In-Reply-To: <005201c502c0$267f4ae0$3d521481@ravard> References: <005201c502c0$267f4ae0$3d521481@ravard> Message-ID: <41F62CCA.9050008@esss.com.br> Hi Oliver, Just call the function inside BOOST_PYTHON_MODULE: BOOST_PYTHON_MODULE(mymodule) { my_init_function(); ... } HTH, Nicodemus. Olivier Ravard wrote: > Hi, > > How to define a C++ function that will be executed automaticaly > when the module is imported ? > > Thanks. > > O.R. > > >------------------------------------------------------------------------ > >_______________________________________________ >C++-sig mailing list >C++-sig at python.org >http://mail.python.org/mailman/listinfo/c++-sig > > From olivier.ravard at novagrid.com Wed Jan 26 12:12:00 2005 From: olivier.ravard at novagrid.com (Olivier Ravard) Date: Wed, 26 Jan 2005 12:12:00 +0100 Subject: [C++-sig] where to store pyd files Message-ID: <003c01c50397$dba64860$3d521481@ravard> Hi, When the compilation is done, the .pyd file created is strored in the boost tree. Is there a way to say to bjam to store the .pyd file in another directiry ? Thanks. O.R. -------------- next part -------------- An HTML attachment was scrubbed... URL: From colin_irwin at hotmail.com Tue Jan 25 08:01:29 2005 From: colin_irwin at hotmail.com (Colin Irwin) Date: Tue, 25 Jan 2005 18:01:29 +1100 Subject: [C++-sig] Conversion between boost::tuple and a python tuple Message-ID: Hi, I have an interface in C++ for which I would like a binding into Python. In particular, one of the functions in the interface takes a boost::tuple argument, e.g.: class ExampleClass { public: ... void foo( boost::tuple int_tuple ); }; I would like to (at least I think I would like to) reflect this into Python such that a user passes in a Python tuple. How would one achieve this? I've searched the BPL documentation and can't seem to find anything. I've also searched the relevant newsgroups and there are some old references (circa 2002) on how to achieve this, but this was with the v1 of the library, so I don't think the ideas/methods are applicable. Finally, is this a good idea? By this I mean, would it be a better idea to change the foo function signature to accept something like a std::vector and then employ an rvalue converter? I realise by doing this the intent of the interface is now a little different, i.e., with above, the user must pass a tuple of 3 values, whilst using a std::vector could lead to any number of integers passed into the function. However, this would make more sense from the Python side and I suspect would be easy (easier?) to code up - some of what I can imagine to be difficulties could result from a mismatch in the python tuple vs. boost::tuple semantics. All help would be much appreciated. The BPL is perfect for what I would like to do, however, I feel I'm lacking a bit of understanding. Colin From rwgk at yahoo.com Thu Jan 27 00:48:00 2005 From: rwgk at yahoo.com (Ralf W. Grosse-Kunstleve) Date: Wed, 26 Jan 2005 15:48:00 -0800 (PST) Subject: [C++-sig] Conversion between boost::tuple and a python tuple In-Reply-To: Message-ID: <20050126234800.18762.qmail@web20221.mail.yahoo.com> --- Colin Irwin wrote: > void foo( boost::tuple int_tuple ); > ... > > All help would be much appreciated. The BPL is perfect for what I would > like to do, however, I feel I'm lacking a bit of understanding. You have the right ideas. The problem is there is not "the one best" answer. If you have only one function like foo, write a "thin wrapper," i.e. a standalone function similar to: void foo_wrapper(ExampleClass& self, boost::python::tuple int_tuple) { // assert len(int_tuple) == 3 // loop over elements of the tuple // use boost::python::extract, copy value to boost_int_tuple self.foo(boost_int_tuple); } ... class_(...) .def("foo", foo_wrapper) ; Note that the standalone C++ function is wrapped as a Python member function. If you have many functions with int_tuple arguments you want to think about writing a custom converter. This is an advanced subject, but we can walk you through. In any case, try the thin wrapper first. You can use it as a starting point for a custom converter. Cheers, Ralf __________________________________ Do you Yahoo!? Yahoo! Mail - You care about security. So do we. http://promotions.yahoo.com/new_mail From colin_irwin at hotmail.com Thu Jan 27 07:33:01 2005 From: colin_irwin at hotmail.com (Colin Irwin) Date: Thu, 27 Jan 2005 17:33:01 +1100 Subject: [C++-sig] Iteration over an enumerated type Message-ID: Hi, One feature that I've occasionally used in C++ is to iterate over all types of an enumerated type. This being possible if one defines the suitable increment (or decrement) operator. So in other words if one had the following enumerated type: enum KnownValue { Value1, Value 2, Value3, }; then the following code could be used, assuming that the increment operator is defined for the enumerated type: for ( KnownValue v = value1; v <= Value3; v++ ) { // ... } I now have a need to do the same thing in Python, with an enumerated type translated from C++. How does one do this? Assuming the enumerated type is translated directly across from C++ into Python (into the module my_module), then I'm been able to do: begin = my_module.KnownValue.Value1 end = my_module.KnownValue.Value3 for v in range( start, end ): # ... I'm far from being an expert in Python, but this has the immediate problem that the range function needs a type one beyond Value3 for the loop to iterate over all useable types. (Indeed, this can also be required in C++ depending on how the loop is written.) I was wondering whether there is a better way to do this in Python, without having to add the extra type? Would it make sense to provide 'begin' and 'end' functions (an extra type to indicate the end would be required, but given I'm talking about providing begin and end functions, then why not)? These could be available in the module, such that the above for loop would look like: for v in range( my_module.KnownValue.begin(), my_module.KnownValue.end() ): # ... Writing this example out, I would be quite happy with this solution, but does anyone have any other suggestions or experiences? Colin From Benjamin_Schmeling at gmx.de Mon Jan 31 23:35:59 2005 From: Benjamin_Schmeling at gmx.de (Benjamin Schmeling) Date: Mon, 31 Jan 2005 23:35:59 +0100 Subject: [C++-sig] implicitly_convertible In-Reply-To: References: Message-ID: <41FEB2CF.4030102@gmx.de> Hi, I have exposed a bigint class which has no constructor for long_ . I added an additional constructor by defining .def("__init__", make_constructor(bigint_constructor)) This works fine. Now I want to use the implicitly_convertible function which expects from the class to have an constructor which takes the first argument (in this case a long_) I used implicitly_convertible but now the problem is that the original c++ class has no such constructor, but the wrapped class. How can I make it using my new constructor in implicitly_convertible? Benjamin