From wz_ at gmx.net Fri Sep 1 01:07:57 2006 From: wz_ at gmx.net (Nicolas Tessore) Date: Fri, 01 Sep 2006 01:07:57 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> Message-ID: <44F76BCD.7000405@gmx.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 djowel at gmail.com Fri Sep 1 01:36:32 2006 From: djowel at gmail.com (Joel de Guzman) Date: Fri, 01 Sep 2006 07:36:32 +0800 Subject: [C++-sig] [tutorial] Auto-Overloading example bug? In-Reply-To: <7465b6170608311021y2f5bebecr90ab1766c5b84ad2@mail.gmail.com> References: <7465b6170608300429n564516bfi22c665cd6cbfca32@mail.gmail.com> <44F666B8.9080609@boost-consulting.com> <44F67B9F.5060802@boost-consulting.com> <7465b6170608311021y2f5bebecr90ab1766c5b84ad2@mail.gmail.com> Message-ID: <44F77280.80103@boost-consulting.com> Roman Yakovenko wrote: > On 8/31/06, Joel de Guzman wrote: >> Ok, disregard that. I did check it out and the error is the def it >> should be: >> >> .def("foo", (void(*)(bool, int, char))0, foo_overloads()); >> >> I fixed the docs and updated to CVS. > > Do you want to consider to fix "def"? > > .def("foo", foo_overloads() ); > > It is not clear why user should pass second argument. I don't think it can be fixed. The compiler does not have enough information in there to know the exact signature needed. I may be wrong though, so I'll investigate. If you know how to implement this, I'm all ears. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net From dave at boost-consulting.com Fri Sep 1 02:53:21 2006 From: dave at boost-consulting.com (David Abrahams) Date: Thu, 31 Aug 2006 20:53:21 -0400 Subject: [C++-sig] boost:python::arg and default value References: <7465b6170607041320j2f745b89xff3f8d44e475b1c0@mail.gmail.com> <7465b6170608311008n5b7ec413p535eeb27e92b3249@mail.gmail.com> Message-ID: "Roman Yakovenko" writes: > On 8/31/06, David Abrahams wrote: >> > I see only one possible solution - to add to Boost.Python >> > functionality, that will >> > allow user to control argument default value conversion time. >> >> I disagree. It should be lazy and do the conversion on demand. Extra >> control is not a significant benefit in this instance. > > Does "lazy and on demand" mean first time a user calls function? Yes... or even the first time a user actually uses the default. > If so, I will try to work on the patch, but I think I still will > need help with boost::python::objects::function class. I'll do my best to help -- Dave Abrahams Boost Consulting www.boost-consulting.com From wz_ at gmx.net Fri Sep 1 09:39:17 2006 From: wz_ at gmx.net (Nicolas Tessore) Date: Fri, 01 Sep 2006 09:39:17 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <44F76BCD.7000405@gmx.net> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> Message-ID: <44F7E3A5.6000604@gmx.net> Nicolas Tessore 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 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" 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 MyClassRef; sizeof(MyClassRef); are not automatically detected and thus, the Mylib::Ref 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. From roman.yakovenko at gmail.com Fri Sep 1 09:55:25 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Fri, 1 Sep 2006 10:55:25 +0300 Subject: [C++-sig] Lost Again! :) In-Reply-To: <44F7E3A5.6000604@gmx.net> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> <44F7E3A5.6000604@gmx.net> Message-ID: <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> On 9/1/06, Nicolas Tessore wrote: > Nicolas Tessore 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 > 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" > 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-module.html 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 MyClassRef; > sizeof(MyClassRef); > > are not automatically detected and thus, the Mylib::Ref > 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/ From wz_ at gmx.net Fri Sep 1 10:01:09 2006 From: wz_ at gmx.net (Nicolas Tessore) Date: Fri, 01 Sep 2006 10:01:09 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> <44F7E3A5.6000604@gmx.net> <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> Message-ID: <44F7E8C5.9030308@gmx.net> Roman Yakovenko wrote: > Please take a look on > http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates-module.html > 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 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. From wz_ at gmx.net Fri Sep 1 12:01:02 2006 From: wz_ at gmx.net (Nicolas Tessore) Date: Fri, 01 Sep 2006 12:01:02 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> <44F7E3A5.6000604@gmx.net> <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> Message-ID: <44F804DE.5020301@gmx.net> Roman Yakovenko wrote: > Please take a look on > http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates-module.html > 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. From jorge.vargas at gmail.com Fri Sep 1 16:04:38 2006 From: jorge.vargas at gmail.com (Jorge Vargas) Date: Fri, 1 Sep 2006 10:04:38 -0400 Subject: [C++-sig] boost python mingw binaries In-Reply-To: <32822fe60608290622l7c0382ffs87219f4532196fdf@mail.gmail.com> References: <32822fe60608281258g669fb64fj23bcd6f46133b89c@mail.gmail.com> <200608291018.53778.achim-bpl@mol-net.com> <32822fe60608290622l7c0382ffs87219f4532196fdf@mail.gmail.com> Message-ID: <32822fe60609010704p7c99ca67i14aa76e8313ccfc4@mail.gmail.com> On 8/29/06, Jorge Vargas wrote: > On 8/29/06, Achim H. wrote: > > Am Montag, 28. August 2006 21:58 schrieb Jorge Vargas: > > > so does anyone has boost python as a binary that works under mingw? > Great thanks > > Yes, I have binaries of 1.33.1 and I can even upload them if you tell me where > > to. > I guess the best place for that is the SF repository, since is the > official site. So I guess we could wait for someone with access there > to reply. > anyone is interested in posting this to SF? From roman.yakovenko at gmail.com Fri Sep 1 16:21:52 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Fri, 1 Sep 2006 16:21:52 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <44F7E8C5.9030308@gmx.net> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> <44F7E3A5.6000604@gmx.net> <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> <44F7E8C5.9030308@gmx.net> Message-ID: <7465b6170609010721y26de3ci2f61af619ee7780f@mail.gmail.com> On 9/1/06, Nicolas Tessore wrote: > Roman Yakovenko wrote: > > Please take a look on > > http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates-module.html > > 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 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_traits-module.html 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_traits-module.html > > 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_declaration.class_t-class.html#aliases 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/ From roman.yakovenko at gmail.com Fri Sep 1 16:26:18 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Fri, 1 Sep 2006 16:26:18 +0200 Subject: [C++-sig] Lost Again! :) In-Reply-To: <44F804DE.5020301@gmx.net> References: <44F6ECDB.3070104@gmx.net> <7465b6170608311033j4c678819o3d91c804f9f2a156@mail.gmail.com> <44F726AF.4010001@gmx.net> <7465b6170608311200j41b6f088tb725d832253338b6@mail.gmail.com> <44F76BCD.7000405@gmx.net> <44F7E3A5.6000604@gmx.net> <7465b6170609010055s371123daje97c9da8ff01b595@mail.gmail.com> <44F804DE.5020301@gmx.net> Message-ID: <7465b6170609010726k6e2a78a1r124cf6e388a542c3@mail.gmail.com> On 9/1/06, Nicolas Tessore wrote: > Roman Yakovenko wrote: > > > Please take a look on > > http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.templates-module.html > > 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_wrappers.calldef_wrapper.free_function_t-class.html http://language-binding.net/pyplusplus/documentation/apidocs/pyplusplus.decl_wrappers.call_policies-module.html Tutorials: http://language-binding.net/pyplusplus/documentation/tutorials/module_builder/module_builder.html http://language-binding.net/pyplusplus/documentation/tutorials/module_builder/generate_code.html -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From lloyd at randombit.net Fri Sep 1 22:25:36 2006 From: lloyd at randombit.net (Jack Lloyd) Date: Fri, 1 Sep 2006 16:25:36 -0400 Subject: [C++-sig] Returning a Python object to C++ (is get_owner the right way?) Message-ID: <20060901202535.GC28064@randombit.net> I have a scenario where I'm wrapping a virtual base class that offers cloning (here, sending a clone message to an object means "return a newly constructed object of whatever type you are"), and want to inherit from that type in Python. Simply implementing that function in Python (eg: class MySubclass(mylib.MyBaseClass): def clone(self): return MySubclass() led to "returning a dangling reference" errors, so I'm using the technique Dave suggested in http://mail.python.org/pipermail/c++-sig/2004-December/008379.html (basically, use get_owner, get ahold of the __class__ attribute, and call the constructor, then keep a reference to the copy-constructed Python object around so it is not destroyed until the lifetime of the C++ object is over, all held inside another class that simply forwards the appropriate messages to the Python object). This has been working fine for me, however since get_owner is still undocumented (AFAICT; couldn't find it anywhere in the 1.33.1 docs), and generally the technique led to some rather ugly code, I wanted to check and see if any new technique/method for dealing with this situation had developed since that discussion? I hope I've managed to explain what I'm doing clearly; if not, I'd be happy to post a minimal example of my method. Thanks, Jack From pirx at cs.tu-berlin.de Sun Sep 3 15:24:52 2006 From: pirx at cs.tu-berlin.de (Andreas) Date: Sun, 03 Sep 2006 15:24:52 +0200 Subject: [C++-sig] problem with tkinter gui running in different interpreters In-Reply-To: References: <002e01c4fa72$d7f3a060$1d02a8c0@wxp2000> <003301c4fa85$0c9d8260$1d02a8c0@wxp2000> Message-ID: <44FAD7A4.2040908@cs.tu-berlin.de> hello, I'm not sure if this is the right place for my question. I have a problem with tkinter running in different python interpreters. I need to separate different python scripts as much as possible. Therefor each script runs in its own interpreter. If only one of the scripts uses tkinter gui and runs the tkinter's mainloop in a created thread, everything is fine. But if more scripts uses this, the whole application with the created dialogs hangs. To solve this only the first script must call tkinter's mainloop(). But thats not an option, because the scripts are independent and must not have dialogs. Thus a script does not know if it is the first which uses tkinter. So the question is: Is it possible to detect from different interpreters whether the tkinter's mainloop is already running or not? Below is the running example code. In main() i want to start multiple dialogs calling startDialog(true), wich does not work. (I'm using boost 1.33.1, MSVC7.1 and Python 2.4.3) Any help would be appreciated, andreas rose void startDialog(bool bCallMainloop) { PyEval_AcquireLock(); PyThreadState* pThreadState = Py_NewInterpreter(); PyThreadState_Swap(pThreadState); char pBuff[] = "Test.exe"; char* Argv[1]; Argv[0] = pBuff; PySys_SetArgv(1, Argv); PyObject* pDict = PyDict_New(); PyDict_SetItemString(pDict, "__builtins__", PyEval_GetBuiltins()); std::string strExec; if (bCallMainloop) { strExec = "\ from threading import * \n\ from Tkinter import * \n\ \n\ class DialogThread(Thread): \n\ def run(self): \n\ label = Label(None, text='hello') \n\ label.pack() \n\ label.mainloop() \n\ \n\ DialogThread().start() \n\ "; } else { strExec = "\ from threading import * \n\ from Tkinter import * \n\ \n\ class DialogThread(Thread): \n\ def run(self): \n\ label = Label(None, text='hello') \n\ label.pack() \n\ \n\ DialogThread().start() \n\ "; } boost::python::handle<> result(PyRun_String(strExec.c_str(), Py_file_input, pDict, pDict)); result.reset(); PyEval_ReleaseThread(pThreadState); } int main(int argc, char** argv) { Py_Initialize(); PyEval_InitThreads(); PyThreadState* pyMainState = PyThreadState_Swap(NULL); PyEval_ReleaseLock(); startDialog(true); startDialog(false); //wait little time to enable user interaction with the dialogs Sleep(10000); PyEval_AcquireLock(); PyThreadState_Swap(pyMainState); Py_Finalize(); return 0; } From Gottfried.Ganssauge at haufe.de Sun Sep 3 16:07:14 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Sun, 3 Sep 2006 16:07:14 +0200 Subject: [C++-sig] Py++ wrapper generation and docstrings In-Reply-To: <7465b6170609030548o13421632if3e04af9d35bd248@mail.gmail.com> Message-ID: <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> > -----Original Message----- > From: Roman Yakovenko [mailto:roman.yakovenko at gmail.com] > Sent: Sunday, September 03, 2006 2:49 PM > To: Ganssauge, Gottfried > Subject: Re: Py++ wrapper generation and docstrings > > On 9/3/06, Ganssauge, Gottfried wrote: > > Hi Roman, > > > > I'm still working on my API with Py++ and there are a few bits left: > > Is this because of Py++ or you have pretty big project :-)? Neither nor I guess. The project is quite old, it's got a C-API and the API is highly irregular :-( > > > 1.) my API contains several functions expecting pointers to callback > > functions. > > Those callbacks get an instance pointer as one of their > arguments > > which has to be supplied as well. > > An example: > > typedef int (*callback_t) (void *instance); > > > > int search (void *instance, callback_t callback); > > > > I have written a generator which generates a wrapper like this: > > > > int wrap_callback_t (void *instance) { > > You can use boost::python::object No I can't :-( Gccxml botches on the bpl headers: $ cat x.hpp # include boost::python::object test (); $ gccxml -I ../../../../../../FremdProdukte/boost2 -I /usr/include/python2.4 x.hpp -fxml=test.xml ../../../../../../FremdProdukte/boost2/boost/python/object_core.hpp:285: sorry, unimplemented: call_expr cannot be mangled due to a defect in the C++ ABI This problem has been reported on the gccxml list already ... > > > try { > > return (boost::python::call > > (reinterpret_cast (instance))); > > } > > > > catch (...) { > > return (-1); // python > exceptions must not > > disrupt program flow > > } > > } > > > > int search_wrapper (PyObject *p) { > > return (search (p, &wrap_callback_t)); > > } > > > > This works quite well, but ... > > How do I make this generator interact with generators already > > supplied by Py++ > > For example: > > you're planning to support automatic conversion of > pointers to > > C++ array arguments from python sequences > > May be the next article will provide you with the answer. > https://realityforge.vrsource.org/view/PyppApi/CodeInserter > > I and Matthias work on this feature this days. Comments and test cases > are welcome :-) I'll have a look at it. > > > Now suppose the following: > > type char array_t [7]; > > > > int search2 (void *instance, callback_t cb, > array_t *result); > > If you already create a wrapper, you can create "better" wrapper: > > boost::python::tuple search2( void* instance, callback_t cb ){ > ... > return boost::python::make_tuple( .... ) > } That's what I'd like to achieve - but automatically! > > > How would both our generators interact with each other? > > I don't see the whole picture, so I can not answer your question. > I assume that you have some functions that take pointer to > callback, right? > You can not expose these functions as is, so you have to > write a wrapper for > them. Basically you should exclude the function from being exported, > and then you > should add your declaration and registration code. Next link should > help you with > your task: > > http://www.language-binding.net/pyplusplus/documentation/inserting_code. html > > > > Finally I'm not sure about when to run my generator. > > In your case you may consider to run it twice: > > 1. first time you can generate your own header file. This file will > contain all wrappers. > 2. second time you weel feed just generated header fileand original > sources to Py++. > > > Currently I'm running it on every declaration > expecting callback- > > and instance pointers. > > The declarations are then modified like this (f is a > declaration > > for "search"): > > pyobject_type = pointer_t (dummy_type_t ("PyObject"))): > > wrapperargs = [ argument_t (name = "instance", type = > > pyobject_type) ] > > function = f.name > > f.name = "%s_wrapper" % function > > f.arguments = wrapperargs > > f.exportable = None # redo the check for exportability > > # rename f if this is the first wrapper > > if not f.alias or f.name == f.alias: > > f.rename (function) > > > > Does this look reasonable? (at least it works :-0) > > No. Too much work and too much details. Consider the way I described. That was my first attempt, but it became difficult to chain several generators together. Eventually I should really consider doing several generator passes to a temp file until the temp file doesn't change anymore. This could take quite some time because gccxml must parse the intermediate files... Furthermore I'm not yet sure how to forward the original function names ... > > > I got another generator which generates wrappers for functions > > expecting "const unsigned char *" arguments for strings ... > > > > 2.) docstring extraction is not really usable at the moment > > consider the attached test case > > [test1.hpp, pypp_test1.py] > > > > When using the "latin1_doc_string" doc_extractor some unicode > > exception is thrown. > > I will take a look on this. I did not thought about unicodes :-(. It > will take some time to > convert Py++ to support it. I think, that doc_extractor will change, > because you will > have to provide encoding. Otherwise, I will not be able to > write code to files. This could be a property on the doc_extractor. > Also quick work around exists: > > my_module > class_< X >( "X" ) > .def( "do_smth", ... ) > ; > > import my_module > my_module.X.__doc__ = .... > my_module.X.do_smth.__doc__ = ... > > This will work and it is simple to generate it. Ok. > > > When using the "ascii_doc_string" doc_extractor invalid code is > > generated > > Only when the doc extractor returns a string which is > conforming to > > C++ syntax everything runs smooth. > > This is how it was created. See explanation later. > > > Pragmatically I would request that doc extractors must return > > docstrings conforming to C++ syntax. > > This means you wouldn't need to change Py++ - just the > > documentation. > > You could supply some function which makes C++-syntax > from a normal > > string like > > def make_cstring (s): > > return ('"%s"' % (repr (s) [1:-1])) > > It is not as simple as you think :-). You have to escape " in the > string and you have to do > it in a smart way. That is why I leaved this to user. If you want we > can work together > to improve the situation. I will make Py++ to work with unicode and > you will contribute > better make_cstring function. Currently I'm using string_escapes = re.compile (r'((\\x[a-f0-9][a-f0-9])|(\\*"))', re.I) def make_cstring (s): def replace_escape(m): g = m.group(1) if g.startswith ('\\x'): return g + '""' elif g == '"': return '\\"' else: return g return '"%s"' % hex_escape.sub (replace_escape, repr (s) [1:-1]) This copes with the problem of hex escapes followed by valid hex characters and with embedded quotes. > > > Can I ask you something? > > Could we switch to one of the mailing lists: pygccxml of boost.python? > I'd like my answers > to be available to other users too. at your request :-) > > It seems that you found work around to "pointer to function" problem. > Can you create > small example with explanation how it should be done. May be I will > able to introduce > this functionality to Py++. Well not for any case. Function pointers without instance pointers still can't be exposed for the reasons given in the reference provided by Py++. Function pointers _with_ instance pointers are a different kind of beast. Generally function declarations using this type of callback have exactly one function pointer argument and exactly one void *argument which is forwarded to the callback function. typedef callback_return_type (*callback_t) (callback_args, void *instance, more callback_args); return_type function (args ..., callback_t, more args, void *instance, more args) Functions having this kind of signature may be wrapped like this: callback_return_type wrap_callback_t (callback_args, void *instance, more callback_args) { PyObject *py_instance = reinterpret_cast (instance); if (py_instance) { try { return (boost::python::call (py_instance, callback_args, more callback_args)) } except (...) { } } return some error value; } return_type function_wrapper (PyObject *instance, args, more_args, ...) { return (function (args ..., &wrap_callback_t, more args, instance, more args)); } I'm attaching the generators module I'm currently using ... The generators are called like this: def wrap_functions (self, decls): """ Generate wrappers for functions otherwise not exportable in their current_form @param decls Function declarations to be wrapped """ wrapper_generators = [ callback_wrapper_generator (self), const_byte_wrapper_generator (self) ] finished = False while not finished: finished = True for d in decls: for g in wrapper_generators: cookie = g.applies (d) if cookie: g (cookie) finished = False break > > Thanks. > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > Cheers, Gottfried -------------- next part -------------- A non-text attachment was scrubbed... Name: generators.py Type: application/octet-stream Size: 9682 bytes Desc: generators.py URL: From roman.yakovenko at gmail.com Sun Sep 3 20:14:27 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Sun, 3 Sep 2006 21:14:27 +0300 Subject: [C++-sig] Py++ wrapper generation and docstrings In-Reply-To: <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> References: <7465b6170609030548o13421632if3e04af9d35bd248@mail.gmail.com> <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> Message-ID: <7465b6170609031114q4d906763y9b61fd5007df2597@mail.gmail.com> On 9/3/06, Ganssauge, Gottfried wrote: > > > Now suppose the following: > > > type char array_t [7]; > > > > > > int search2 (void *instance, callback_t cb, > > array_t *result); > > > > If you already create a wrapper, you can create "better" wrapper: > > > > boost::python::tuple search2( void* instance, callback_t cb ){ > > ... > > return boost::python::make_tuple( .... ) > > } > That's what I'd like to achieve - but automatically! Lets be more productive. Can you create small example, that you want to export and Py++ script and I will make it work? > > > > > How would both our generators interact with each other? > > > > I don't see the whole picture, so I can not answer your question. > > I assume that you have some functions that take pointer to > > callback, right? > > You can not expose these functions as is, so you have to > > write a wrapper for > > them. Basically you should exclude the function from being exported, > > and then you > > should add your declaration and registration code. Next link should > > help you with > > your task: > > > > > http://www.language-binding.net/pyplusplus/documentation/inserting_code. > html > > > > > > > Finally I'm not sure about when to run my generator. > > > > In your case you may consider to run it twice: > > > > 1. first time you can generate your own header file. This file will > > contain all wrappers. > > 2. second time you weel feed just generated header fileand original > > sources to Py++. > > > That was my first attempt, but it became difficult to chain several > generators together. > Eventually I should really consider doing several generator passes to a > temp file until the temp file doesn't change anymore. > This could take quite some time because gccxml must parse the > intermediate files... > Furthermore I'm not yet sure how to forward the original function names > ... I still fill that I don't have enough information to help you. For the last problem I can give you small hint: mangle generated function name. Take a look on boost_random example: http://tinyurl.com/gwc2t http://tinyurl.com/kocap I introduced small convention about struct names and than I reused this information from the script. > > > > > I got another generator which generates wrappers for functions > > > expecting "const unsigned char *" arguments for strings ... > > > > > > 2.) docstring extraction is not really usable at the moment > > > consider the attached test case > > > [test1.hpp, pypp_test1.py] > > > > > > When using the "latin1_doc_string" doc_extractor some unicode > > > exception is thrown. > > > > I will take a look on this. I did not thought about unicodes :-(. It > > will take some time to > > convert Py++ to support it. I think, that doc_extractor will change, > > because you will > > have to provide encoding. Otherwise, I will not be able to > > write code to files. > This could be a property on the doc_extractor. Yes I know, that is exactly what I meant by "doc_extractor" will change. > Currently I'm using > string_escapes = re.compile (r'((\\x[a-f0-9][a-f0-9])|(\\*"))', > re.I) > def make_cstring (s): > def replace_escape(m): > g = m.group(1) > if g.startswith ('\\x'): > return g + '""' > elif g == '"': > return '\\"' > else: > return g > > return '"%s"' % hex_escape.sub (replace_escape, repr (s) [1:-1]) > > This copes with the problem of hex escapes followed by valid hex > characters and with embedded quotes. May I copy this code to Py++ contrib package under the license( http://www.boost.org/more/license_info.html ) > > It seems that you found work around to "pointer to function" problem. > > Can you create > > small example with explanation how it should be done. May be I will > > able to introduce > > this functionality to Py++. > Well not for any case. > Function pointers without instance pointers still can't be exposed for > the reasons given in the reference provided by Py++. > Function pointers _with_ instance pointers are a different kind of > beast. > Generally function declarations using this type of callback have exactly > one function pointer argument and exactly one void *argument which is > forwarded to the callback function. > typedef callback_return_type (*callback_t) (callback_args, void > *instance, more callback_args); > > return_type function (args ..., callback_t, more args, void > *instance, more args) > > Functions having this kind of signature may be wrapped like this: > > callback_return_type wrap_callback_t (callback_args, void > *instance, more callback_args) { > PyObject *py_instance = reinterpret_cast > (instance); > > if (py_instance) { > try { > return > (boost::python::call (py_instance, callback_args, > more callback_args)) > } > > except (...) { > } > } > > return some error value; > } > > return_type function_wrapper (PyObject *instance, args, > more_args, ...) { > return (function (args ..., &wrap_callback_t, more args, > instance, more args)); > } > > I'm attaching the generators module I'm currently using ... > The generators are called like this: > def wrap_functions (self, decls): > """ > Generate wrappers for functions otherwise not exportable in > their > current_form > > @param decls > Function declarations to be wrapped > """ > wrapper_generators = [ > callback_wrapper_generator (self), > const_byte_wrapper_generator (self) > ] > finished = False > while not finished: > finished = True > for d in decls: > for g in wrapper_generators: > cookie = g.applies (d) > if cookie: > g (cookie) > finished = False > break > Thank you for explanation. May I copy this code to Py++ contrib package under the license( http://www.boost.org/more/license_info.html ) -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From roman.yakovenko at gmail.com Sun Sep 3 21:33:06 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Sun, 3 Sep 2006 22:33:06 +0300 Subject: [C++-sig] Py++ wrapper generation and docstrings In-Reply-To: <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> References: <7465b6170609030548o13421632if3e04af9d35bd248@mail.gmail.com> <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> Message-ID: <7465b6170609031233r7ffa8c38nd9091329d4b96aaa@mail.gmail.com> On 9/3/06, Ganssauge, Gottfried wrote: > > > 2.) docstring extraction is not really usable at the moment > > > consider the attached test case > > > [test1.hpp, pypp_test1.py] > > > > > > When using the "latin1_doc_string" doc_extractor some unicode > > > exception is thrown. I added this to the project "todo" list. I hope it will be addressed before next release. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From ganssauge at gmx.de Sun Sep 3 23:06:42 2006 From: ganssauge at gmx.de (=?ISO-8859-1?Q?Gottfried_Gan=DFauge?=) Date: Sun, 03 Sep 2006 23:06:42 +0200 Subject: [C++-sig] Py++ wrapper generation and docstrings In-Reply-To: <7465b6170609031114q4d906763y9b61fd5007df2597@mail.gmail.com> References: <7465b6170609030548o13421632if3e04af9d35bd248@mail.gmail.com> <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> <7465b6170609031114q4d906763y9b61fd5007df2597@mail.gmail.com> Message-ID: <44FB43E2.8030408@gmx.de> Roman Yakovenko schrieb: > On 9/3/06, Ganssauge, Gottfried wrote: >>>> Now suppose the following: >>>> type char array_t [7]; >>>> >>>> int search2 (void *instance, callback_t cb, >>> array_t *result); >>> >>> If you already create a wrapper, you can create "better" wrapper: >>> >>> boost::python::tuple search2( void* instance, callback_t cb ){ >>> ... >>> return boost::python::make_tuple( .... ) >>> } >> That's what I'd like to achieve - but automatically! > > Lets be more productive. Can you create small example, that you want to export > and Py++ script and I will make it work? Don't get me wrong, I don't want you to do my job - in principle it already works using the generator module I posted. What I wanted to achieve is interoperability with Py++'s infrastructure (I figure I'm sharing goals with the pypp project here ...) Please see test1* attachments. What I have is: test1_bindings.cpp are generated What I want is: test1_bindings.cpp.wanted ... >> Eventually I should really consider doing several generator passes to a >> temp file until the temp file doesn't change anymore. >> This could take quite some time because gccxml must parse the >> intermediate files... >> Furthermore I'm not yet sure how to forward the original function names >> ... > > I still fill that I don't have enough information to help you. For the > last problem I > can give you small hint: mangle generated function name. You can see that in action on my sample project already - I simply add "_wrapper". Momentarily I'm not using that regularity but modify the original declaration instead. > > Take a look on boost_random example: > http://tinyurl.com/gwc2t > http://tinyurl.com/kocap will do ... >>>> 2.) docstring extraction is not really usable at the moment >>>> consider the attached test case >>>> [test1.hpp, pypp_test1.py] ... > >> Currently I'm using >> string_escapes = re.compile (r'((\\x[a-f0-9][a-f0-9])|(\\*"))', >> re.I) >> def make_cstring (s): >> def replace_escape(m): >> g = m.group(1) >> if g.startswith ('\\x'): >> return g + '""' >> elif g == '"': >> return '\\"' >> else: >> return g >> >> return '"%s"' % hex_escape.sub (replace_escape, repr (s) [1:-1]) >> >> This copes with the problem of hex escapes followed by valid hex >> characters and with embedded quotes. > > May I copy this code to Py++ contrib package under the license( > http://www.boost.org/more/license_info.html ) Please do! > >>> It seems that you found work around to "pointer to function" problem. >>> Can you create >>> small example with explanation how it should be done. May be I will >>> able to introduce >>> this functionality to Py++. ... > Thank you for explanation. > > May I copy this code to Py++ contrib package under the license( > http://www.boost.org/more/license_info.html ) Of course, please do so. Cheers, Gottfried -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: test1.hpp URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: test1_bindings.cpp URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: test1_bindings.cpp.wanted URL: From roman.yakovenko at gmail.com Mon Sep 4 08:09:36 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Mon, 4 Sep 2006 09:09:36 +0300 Subject: [C++-sig] Py++ wrapper generation and docstrings In-Reply-To: <44FB43E2.8030408@gmx.de> References: <7465b6170609030548o13421632if3e04af9d35bd248@mail.gmail.com> <51F4AD92DB06E9488BBC39B7B492409E0162AAB0@vg20ex1.grp.haufemg.com> <7465b6170609031114q4d906763y9b61fd5007df2597@mail.gmail.com> <44FB43E2.8030408@gmx.de> Message-ID: <7465b6170609032309vfab77bbp9ecbce481343395a@mail.gmail.com> On 9/4/06, Gottfried Gan?auge wrote: > Don't get me wrong, I don't want you to do my job - in principle it > already works using the generator module I posted. There is an ongoing discussion about improving Py++ usability by introducing DSL. Problem definition: http://www.language-binding.net/pyplusplus/peps/dsl_challenge.html Wiki page: https://realityforge.vrsource.org/view/PyppApi/DslDiscussion So, I would like to see how you use Py++. It will help me to make it better. > What I wanted to achieve is interoperability with Py++'s infrastructure > (I figure I'm sharing goals with the pypp project here ...) > > Please see test1* attachments. > What I have is: > test1_bindings.cpp are generated > What I want is: > test1_bindings.cpp.wanted You did not attached files :-( P.S. Thank you for contribution -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From baas at ira.uka.de Mon Sep 4 17:43:01 2006 From: baas at ira.uka.de (Matthias Baas) Date: Mon, 04 Sep 2006 17:43:01 +0200 Subject: [C++-sig] What if a Python override returns several values? Message-ID: Hi, how can I obtain the result tuple from calling a Python override that returns several values? The following example is from the tutorial and works fine as long as the Python implementation of f returns an integer. struct BaseWrap : Base, wrapper { int f() { return this->get_override("f")(); } }; But if I have another virtual member function "void g(int& a, int &b)" which returns two integers, then I'd like the Python version to take no arguments and return a tuple (a,b). But how does the wrapper look like in this case? I would have expected something like: void g(int& a, int& b) { boost::python::tuple tup = this->get_override("g")(); a = ...extract an int from tup[0]... b = ...extract an int from tup[1]... } But when I run this code I get the following error at runtime: TypeError: No registered converter was able to extract a C++ reference to type boost::python::tuple from this Python object of type tuple So how is this dealt with using the "wrapper" class? (This is Boost.Python v1.33.1 on Linux) - Matthias - From kir at lapshin.net Tue Sep 5 17:28:05 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Tue, 05 Sep 2006 19:28:05 +0400 Subject: [C++-sig] [Py++] First imressions Message-ID: <44FD9785.9000204@lapshin.net> Hello, Recently I was charged with exposing our project to Python, and naturally went to Boost.Python documentation. After digging a bit, learning, etc, I decided to give some code generator a try -- so the choice was Pyste or Py++. I've decided to try the latter one first, since it seems to have quite powerful query language, and was offering a promise of doing certain operations in bulk. Another reason was that Py++ is actively maintained. Long story short, I dived in, and I haven't look back. I am quite happy with progress, albeit the initial development is not finished yet, so it is not a success story yet, but I am quite confident it will become one quite soon. I would like to thank Roman for his hard work on Py++ and for being extremely helpful in our private e-mail discussion. Just for the record I would like to post some of the problems I had and the way they were resolved. 1. The way overrides are generated does not compile on MSVC8 (2005). Looks like the problem is in conversion of return type if return type is bool or enum. For example virtual bool is_representative( ) const { bp::override func_is_representative = this->get_override( "is_representative" ); return func_is_representative( ); // errors out } error C2440: 'return' : cannot convert from 'boost::python::detail::method_result' to 'bool' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called Don't know why is this happening, but the good news, there is a workaround. One can use explicit conversion of return type, i.e. return func_is_representative()..as(&boost::type()); If someone could verify this problem, I guess the solution would be to patch code creator. 2. How to disable function overriding. I don't really need ability to override virtual functions from Python anyway, and moreover using wrapper classes does not seem to work for me, since I am trying to expose abstract interfaces to python and hide concrete implementations (hence wrapper is abstract as well and can't be instantiated). Maybe there is still a way to expose it with wrapper, but I've decided not bother for now. Roman suggested following way to suppress overriding: from pygccxml import declarations members = cls.decls( declarations.virtuality_type_matcher( declarations.VIRTUALITY_TYPES.VIRTUAL ) , decl_type=pd.member_calldef_t , allow_empty=True) members.set_virtuality( declarations.VIRTUALITY_TYPES.NOT_VIRTUAL ) Note that Py++ differentiates between VIRTUAL and PURE_VIRTUAL, so above listed code does not cover pure virtual functions. 3. Observation: Py++ generates wrappers even if there is no virtual functions, but there is nested class/struct. Nested enums are Ok. 4. Gccxml is buggy, especially with respect to default arguments. See http://language-binding.net/pygccxml/design.html#patchers. In my case I had problems with default std::vector arguments. Those can be worked around manually with mb = module_builder_t( ... ) Foo = mb.class_( 'Foo' ) Foo_constructor = Foo.constructor( select write constructor ) #help: http://language-binding.net/pygccxml/query_interface.html Foo_constructor.arguments[0].default_value = fixed default value 5. Precompiled header support is not implemented even though documentation claims it is. Roman says it is in works. For a meantime one can use following workaround: mb.code_creator.adopt_creator( code_creators.include_t(header='_pch.hpp'), 0) md.split_module(...) 6. shared_ptr works out of the box, while shared_ptr does not. Roman gave me following pointers: http://boost.org/libs/python/doc/v2/register_ptr_to_python.html Also read this: http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.type_traits.smart_pointer_traits-class.html Now you can implement some general solution similar to http://python-ogre.python-hosting.com/file/trunk/python-ogre/shared_ptr.py I did not have time to try it yet, but planning to do it soon. Cheers, Kirill From kir at lapshin.net Tue Sep 5 17:40:31 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Tue, 05 Sep 2006 19:40:31 +0400 Subject: [C++-sig] [Py++] Nested enum as default arg Message-ID: Hi, Suppose I have struct Foo { enum Bar {BAR1, BAR2}; explicit Foo(Bar arg = BAR1); }; Py++ generates code that tries to add constructor (and default argument) prior to enum being registered. Result is exception in module import. Any ideas how to fix / work around? Other then moving enum outside the class? Cheers, Kirill From amohr at pixar.com Tue Sep 5 18:53:54 2006 From: amohr at pixar.com (Alex Mohr) Date: Tue, 05 Sep 2006 09:53:54 -0700 Subject: [C++-sig] What if a Python override returns several values? In-Reply-To: References: Message-ID: <44FDABA2.60809@pixar.com> > But if I have another virtual member function "void g(int& a, int &b)" > which returns two integers, then I'd like the Python version to take no > arguments and return a tuple (a,b). But how does the wrapper look like > in this case? I would have expected something like: > > void g(int& a, int& b) > { > boost::python::tuple tup = this->get_override("g")(); > > a = ...extract an int from tup[0]... > b = ...extract an int from tup[1]... > } > > But when I run this code I get the following error at runtime: > > TypeError: No registered converter was able to extract a C++ reference > to type boost::python::tuple from this Python object of type tuple Not sure exactly what's going on here, but you might be able to find out by looking at override.hpp. Look at method_result -- that's what you're getting back from get_override. Off the top of my head, I think this would probably work for you: tuple tup = call(this->get_override("g").ptr()); a = ...extract an int from tup[0] b = ...extract an int from tup[1] It's certainly not as nice as what you wrote, but I have a feeling it might make the conversions work right. The idea here is that the boost::python::override object manages the python callable object, so you can get it (using ptr()) and call it any way you like. Alex From baas at ira.uka.de Tue Sep 5 19:30:27 2006 From: baas at ira.uka.de (Matthias Baas) Date: Tue, 05 Sep 2006 19:30:27 +0200 Subject: [C++-sig] What if a Python override returns several values? In-Reply-To: <44FDABA2.60809@pixar.com> References: <44FDABA2.60809@pixar.com> Message-ID: Alex Mohr wrote: >> void g(int& a, int& b) >> { >> boost::python::tuple tup = this->get_override("g")(); >> >> a = ...extract an int from tup[0]... >> b = ...extract an int from tup[1]... >> } >> >> But when I run this code I get the following error at runtime: >> >> TypeError: No registered converter was able to extract a C++ reference >> to type boost::python::tuple from this Python object of type tuple > > [...] > Off the top of my head, I think this would probably work for you: > > tuple tup = call(this->get_override("g").ptr()); Excellent! This works, thanks! - Matthias - From roman.yakovenko at gmail.com Tue Sep 5 20:00:12 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 5 Sep 2006 21:00:12 +0300 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: References: Message-ID: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> On 9/5/06, Kirill Lapshin wrote: > Hi, > > Suppose I have > > struct Foo > { > enum Bar {BAR1, BAR2}; > > explicit Foo(Bar arg = BAR1); > }; > > > Py++ generates code that tries to add constructor (and default argument) > prior to enum being registered. Result is exception in module import. > > Any ideas how to fix / work around? Other then moving enum outside the > class? mb = module_builder_t( ... ) Foo = mb.constructor( 'Foo' ) #I assume that there is only one constructor Foo.arguments[0].default_value = 'int(%s)' % Foo.arguments[0].default_value You are not the first one who has this problem. Another work around is: using boost::python; class_< Foo > foo( "Foo", no_init ); scope foo_scope( foo ); enum_< ... >...; foo_scope.def( init< ... >( ... ) ); If you search this mailing list you will find few discussions about this problem. I hope I will be able to submit patch to the library that will solve "default arguments" dependency problem. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From roman.yakovenko at gmail.com Tue Sep 5 22:03:23 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 5 Sep 2006 23:03:23 +0300 Subject: [C++-sig] custom smart pointers In-Reply-To: <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> Message-ID: <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> On 8/31/06, Roman Yakovenko wrote: > On 8/31/06, David Abrahams wrote: > > >From this I can't understand what you're doing or what errors you're > > getting. Please do what I tell everyone to do: make a _complete_, > > _minimal_ example that reproduces your problem and post that. > > I attached 3 files. This is complete and minimal example. > > custom_smart_ptr.h > file contains smart pointer class definition. > > custom_smart_ptr_classes_to_be_exported.hpp > file contains definition of 2 classes: "base" and "derived" classes. > This file also defines "get_value" function. this function is > called from Python. > > custom_smart_ptr_classes.cpp > file contains Boost.Python bindings. > > Python code is next: > import custom_smart_ptr_classes as cspc > d = cspc.derived( 2 ) > cspc.get_value( d ) > > The last line raises next exception: > > ArgumentError: Python argument types in > custom_smart_ptr_classes.get_value(derived) > did not match C++ signature: > get_value(my_smart_ptr_t a) > > Thank you. Can somebody help me with this issue? Thanks in advance. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From amohr at pixar.com Tue Sep 5 22:20:20 2006 From: amohr at pixar.com (Alex Mohr) Date: Tue, 05 Sep 2006 13:20:20 -0700 Subject: [C++-sig] custom smart pointers In-Reply-To: <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> Message-ID: <44FDDC04.3010200@pixar.com> >> Python code is next: >> import custom_smart_ptr_classes as cspc >> d = cspc.derived( 2 ) >> cspc.get_value( d ) >> >> The last line raises next exception: >> >> ArgumentError: Python argument types in >> custom_smart_ptr_classes.get_value(derived) >> did not match C++ signature: >> get_value(my_smart_ptr_t a) >> >> Thank you. > > Can somebody help me with this issue? > > Thanks in advance. In my experience, boost python needs a lot of hand holding to work well with custom smart pointers. I think the first thing you need here is an rvalue from-python conversion for your smart pointers. Register a conversion for each smart_ptr that you expose to python. And make sure you do it for smart_ptr, not smart_ptr > in the case of polymorphic stuff. I (semi)automate this in a custom def visitor. Alex From abierbaum at gmail.com Wed Sep 6 01:09:12 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Tue, 5 Sep 2006 18:09:12 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44F5CD10.5010103@pixar.com> References: <44F5CD10.5010103@pixar.com> Message-ID: On 8/30/06, Alex Mohr wrote: > > What I need is a way to tell boost python that anytime it needs to > > convert a ptr to python it should first convert it to a > > ref_ptr (using a standard copy constructor in ref_ptr<>) and > > then use this ref_ptr as the held type like normal. > > > > At first I thought that implicitly_convertible<> would help: > > > > implicitly_convertible, ref_ptr >(); > > > > But this doesn't seem to do anything for me. (this really isn't too > > surprising since this isn't what implicitly_convertible is for, but it > > seemed worth a try). > > > > Has anyone else ran into anything similar? Any ideas? > > At first glance, it seems like you want to register a to-python > conversion for all your ptr types. Note that all code I write in > this message is untested: > > template > struct ptr_to_python { > static PyObject *convert(ptr const &p) { > return Py_INCREF(object(ref_ptr(p)).ptr()); > } > }; > > Then you need to do this for each class you register: > > to_python_converter, ptr_to_python >(); > Thanks Alex, this worked great. I had to change the Py_INCREF to a bp::incref but otherwise things are all good. But now I have a rather strange followup question. It seems that Boost.Python is doing some magic behind the scenes to convert an object coming from C++ as a smart pointer whose wrapped pointer is NULL into a Python "None". The is great, and was a wonderful surprise. But now I need to find a way to make it happen in the other direction. How does boost.python convert a parameter of "None" into an object/smart_ptr to pass to C++? I need to find a way to call a C++ method like: void setObject(ptr obj); from Python and call it in Python as "setObject(None)" and instruct boost.python to convert this into a call behind the scenes in C++ to: setObject(NullPtr); where "NullPtr" is a global const value defined by the library that is used to signify a NULL shared pointer throughout the system. (the reason it needs something like this is a little complex, but it is not my library so I can't change this part much.) Alternatively, I could probably make it work if I could get boost.python to make a call like: setObject(ref_ptr(NULL) ) as I think I could get the library to automatically convert ref_ptr(NULL) into a NullPtr. Any ideas? -Allen From amohr at pixar.com Wed Sep 6 01:39:30 2006 From: amohr at pixar.com (Alex Mohr) Date: Tue, 05 Sep 2006 16:39:30 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> Message-ID: <44FE0AB2.8010006@pixar.com> > Thanks Alex, this worked great. I had to change the Py_INCREF to a > bp::incref but otherwise things are all good. > > But now I have a rather strange followup question. > > It seems that Boost.Python is doing some magic behind the scenes to > convert an object coming from C++ as a smart pointer whose wrapped > pointer is NULL into a Python "None". The is great, and was a > wonderful surprise. But now I need to find a way to make it happen in > the other direction. > > How does boost.python convert a parameter of "None" into an > object/smart_ptr to pass to C++? It happens in the from_python conversion. It just checks for None and (I believe) default-constructs a the pointer object. Is it the case that default-constructing one of your smart pointers does not produce the intended NULL? It probably wouldn't be hard to add a customization (paralleling get_pointer and pointee) to boost python. But in the meantime... > I need to find a way to call a C++ method like: > > void setObject(ptr obj); > > from Python and call it in Python as "setObject(None)" and instruct > boost.python to convert this into a call behind the scenes in C++ to: > > setObject(NullPtr); > > where "NullPtr" is a global const value defined by the library that is > used to signify a NULL shared pointer throughout the system. (the > reason it needs something like this is a little complex, but it is not > my library so I can't change this part much.) > > Alternatively, I could probably make it work if I could get > boost.python to make a call like: > > setObject(ref_ptr(NULL) ) > > as I think I could get the library to automatically convert > ref_ptr(NULL) into a NullPtr. > > Any ideas? I think you can do either version by registering your own rvalue from_python converters for all your pointer types. You can do this in the def_visitor along with the to_python conversion we discussed earlier. Just replace the relevant bits below ("Deal with the "None" case") with whatever you want. Again, I'm just typing this so it may not compile, and no guarantees of course... template struct smart_ptr_from_python { typedef typename boost::python::pointee::type Pointee; smart_ptr_from_python() { converter::registry::insert(&convertible, &construct, type_id()); } private: static void *convertible(PyObject *p) { // can always produce a pointer from None. if (p == Py_None) return p; // Otherwise, we can do it if we can get the pointee out. void *result = converter::get_lvalue_from_python (p, converter::registered::converters); return result; } static void construct(PyObject* source, converter:: rvalue_from_python_stage1_data* data) { void* const storage = ((converter::rvalue_from_python_storage*)data)-> storage.bytes; // Deal with the "None" case. if (data->convertible == source) new (storage) Ptr(); // Or whatever you want. else new (storage) Ptr(static_cast(data->convertible)); data->convertible = storage; } }; Alex From abierbaum at gmail.com Wed Sep 6 03:44:38 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Tue, 5 Sep 2006 20:44:38 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FE0AB2.8010006@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: On 9/5/06, Alex Mohr wrote: > > Thanks Alex, this worked great. I had to change the Py_INCREF to a > > bp::incref but otherwise things are all good. > > > > But now I have a rather strange followup question. > > > > It seems that Boost.Python is doing some magic behind the scenes to > > convert an object coming from C++ as a smart pointer whose wrapped > > pointer is NULL into a Python "None". The is great, and was a > > wonderful surprise. But now I need to find a way to make it happen in > > the other direction. > > > > How does boost.python convert a parameter of "None" into an > > object/smart_ptr to pass to C++? > > It happens in the from_python conversion. It just checks for None and > (I believe) default-constructs a the pointer object. Is it the case > that default-constructing one of your smart pointers does not produce > the intended NULL? It probably wouldn't be hard to add a customization > (paralleling get_pointer and pointee) to boost python. But in the > meantime... I will try to find this in the boost.python code and verify the behavior. > > > I need to find a way to call a C++ method like: > > > > void setObject(ptr obj); > > > > from Python and call it in Python as "setObject(None)" and instruct > > boost.python to convert this into a call behind the scenes in C++ to: > > > > setObject(NullPtr); > > > > where "NullPtr" is a global const value defined by the library that is > > used to signify a NULL shared pointer throughout the system. (the > > reason it needs something like this is a little complex, but it is not > > my library so I can't change this part much.) > > > > Alternatively, I could probably make it work if I could get > > boost.python to make a call like: > > > > setObject(ref_ptr(NULL) ) > > > > as I think I could get the library to automatically convert > > ref_ptr(NULL) into a NullPtr. > > > > Any ideas? > > I think you can do either version by registering your own rvalue > from_python converters for all your pointer types. You can do this in > the def_visitor along with the to_python conversion we discussed earlier. > > Just replace the relevant bits below ("Deal with the "None" case") with > whatever you want. > > Again, I'm just typing this so it may not compile, and no guarantees of > course... All I can say is "wow!!". You seem to understand the conversion process inside boost.python much more then I do. I will give these methods a try tomorrow. I will need to alter them slightly since I am not using the def_visitor method you outlined. (I am using Py++ to generate the bindings so it really doesn't take any more typing to just have it put the registration calls in the right place). I will let you know how it goes. As a side note, if you don't mind me asking, how did you learn so much about how the conversion process works. I have always had trouble understanding the full process and am looking for any advice about how to learn it better. (did you learn from the code, the API reference, the mailing list, other??) If you ever have any time or interest and wanted to contribute some to a little documentation effort I am working on in my spare time, take a look at http://tinyurl.com/zb76h . Thanks again. -Allen > > template > struct smart_ptr_from_python { > typedef typename boost::python::pointee::type Pointee; > smart_ptr_from_python() { > converter::registry::insert(&convertible, &construct, > type_id()); > } > private: > static void *convertible(PyObject *p) { > // can always produce a pointer from None. > if (p == Py_None) > return p; > // Otherwise, we can do it if we can get the pointee out. > void *result = converter::get_lvalue_from_python > (p, converter::registered::converters); > return result; > } > > static void construct(PyObject* source, converter:: > rvalue_from_python_stage1_data* data) { > void* const storage = > ((converter::rvalue_from_python_storage*)data)-> > storage.bytes; > // Deal with the "None" case. > if (data->convertible == source) > new (storage) Ptr(); // Or whatever you want. > else > new (storage) > Ptr(static_cast(data->convertible)); > data->convertible = storage; > } > }; > > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From roman.yakovenko at gmail.com Wed Sep 6 08:16:33 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Wed, 6 Sep 2006 09:16:33 +0300 Subject: [C++-sig] custom smart pointers In-Reply-To: <44FDDC04.3010200@pixar.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> <44FDDC04.3010200@pixar.com> Message-ID: <7465b6170609052316w887a0b5v3723de9d1833491e@mail.gmail.com> On 9/5/06, Alex Mohr wrote: > In my experience, boost python needs a lot of hand holding to work well > with custom smart pointers. > > I think the first thing you need here is an rvalue from-python > conversion for your smart pointers. I don't know and understand how I should do it, really :-(. I took a look on shared_ptr_from_python class. I understand the code which is written in construct function. static void construct(PyObject* source, rvalue_from_python_stage1_data* data) { ... new (storage) shared_ptr( static_cast(data->convertible), shared_ptr_deleter(handle<>(borrowed(source))) ); ... } Boost.Python creates new instance of shared_ptr with custom deleter. This way it says to shared_ptr that the object is already managed. The smart pointer, the project use, does not provide this functionality. More over, I don't understand what data->convertible will contain. > Register a conversion for each > smart_ptr that you expose to python. And make sure you do it for > smart_ptr, not smart_ptr > in the case of polymorphic stuff. I think I do it: register_ptr_to_python< my_smart_ptr_t< base > >(); register_ptr_to_python< my_smart_ptr_t< derived > >(); implicitly_convertible< my_smart_ptr_t< derived >, my_smart_ptr_t< base > >(); This is what yoy mean, right? Many thanks for your help. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From amohr at pixar.com Wed Sep 6 18:36:08 2006 From: amohr at pixar.com (Alex Mohr) Date: Wed, 06 Sep 2006 09:36:08 -0700 Subject: [C++-sig] custom smart pointers In-Reply-To: <7465b6170609052316w887a0b5v3723de9d1833491e@mail.gmail.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> <44FDDC04.3010200@pixar.com> <7465b6170609052316w887a0b5v3723de9d1833491e@mail.gmail.com> Message-ID: <44FEF8F8.8080004@pixar.com> > I don't know and understand how I should do it, really :-(. > > Boost.Python creates new instance of shared_ptr with custom deleter. This way it > says to shared_ptr that the object is already managed. I believe it's just a hack to do what I call "object identity" -- which is just tracking the association between a C++ instance and a python object. When converting a shared ptr to-python, boost python checks to see if it has its special deleter, and will use that to produce the python object rather than constructing a new one. This is a fragile scheme. It fails frequently for shared ptrs, as has been discussed on this list before, and it doesn't work at all for custom shared pointers. Anyway, I consider object identity to be a different issue from the one we're currently discussing. But I do think you should address it in py++. We can talk about that later. > The smart pointer, the project use, does not provide this > functionality. More over, > I don't understand what data->convertible will contain. If I recall correctly (I'm not looking at the code) data->convertible is the result that the convertible method returned, so in this case it's a raw pointer to the C++ instance. > I think I do it: > > register_ptr_to_python< my_smart_ptr_t< base > >(); > register_ptr_to_python< my_smart_ptr_t< derived > >(); > implicitly_convertible< my_smart_ptr_t< derived >, my_smart_ptr_t< base > >(); > > This is what yoy mean, right? No, these are to-python conversions. I'm talking about rvalue from-python conversions. Have a look at the last few messages in the concurrent thread on this list with subject "Is there a way to automatically convert a smart_ptr to a held_type (try 2)". I posted a message to that thread which has some (untested) smart pointer rvalue from-python conversion code in it. Actually -- it probably looks something like shared_ptr_from_python. > Many thanks for your help. You're welcome. Alex From amohr at pixar.com Wed Sep 6 18:42:37 2006 From: amohr at pixar.com (Alex Mohr) Date: Wed, 06 Sep 2006 09:42:37 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: <44FEFA7D.8020606@pixar.com> > As a side note, if you don't mind me asking, how did you learn so much > about how the conversion process works. I have always had trouble > understanding the full process and am looking for any advice about how > to learn it better. (did you learn from the code, the API reference, > the mailing list, other??) If you ever have any time or interest and > wanted to contribute some to a little documentation effort I am > working on in my spare time, take a look at http://tinyurl.com/zb76h . I learned from a combination of all the things you mention. I currently find reading the code to be the most useful. I don't know if there's a better resource, other than getting David to respond to your questions directly if you can. :) Alex From abierbaum at gmail.com Wed Sep 6 19:02:06 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 12:02:06 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FEFA7D.8020606@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FEFA7D.8020606@pixar.com> Message-ID: I've been trying to learn more about the calling and argument conversion process today by stepping through the code with ddd/gdb. I am learning some things but I have to admit it is pretty difficult with all the preprocessor library and MPL usage (this stuff confuses the debugger quite a bit). Hopefully by later today I will understand enough to know what you code samples are trying to do. :) -Allen On 9/6/06, Alex Mohr wrote: > > As a side note, if you don't mind me asking, how did you learn so much > > about how the conversion process works. I have always had trouble > > understanding the full process and am looking for any advice about how > > to learn it better. (did you learn from the code, the API reference, > > the mailing list, other??) If you ever have any time or interest and > > wanted to contribute some to a little documentation effort I am > > working on in my spare time, take a look at http://tinyurl.com/zb76h . > > I learned from a combination of all the things you mention. I currently > find reading the code to be the most useful. I don't know if there's a > better resource, other than getting David to respond to your questions > directly if you can. :) > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From abierbaum at gmail.com Wed Sep 6 21:17:12 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 14:17:12 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FE0AB2.8010006@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: On 9/5/06, Alex Mohr wrote: > > Thanks Alex, this worked great. I had to change the Py_INCREF to a > > bp::incref but otherwise things are all good. > > > > But now I have a rather strange followup question. > > > > It seems that Boost.Python is doing some magic behind the scenes to > > convert an object coming from C++ as a smart pointer whose wrapped > > pointer is NULL into a Python "None". The is great, and was a > > wonderful surprise. But now I need to find a way to make it happen in > > the other direction. > > > > How does boost.python convert a parameter of "None" into an > > object/smart_ptr to pass to C++? > > It happens in the from_python conversion. It just checks for None and > (I believe) default-constructs a the pointer object. Is it the case > that default-constructing one of your smart pointers does not produce > the intended NULL? It probably wouldn't be hard to add a customization > (paralleling get_pointer and pointee) to boost python. But in the > meantime... > > > I need to find a way to call a C++ method like: > > > > void setObject(ptr obj); > > > > from Python and call it in Python as "setObject(None)" and instruct > > boost.python to convert this into a call behind the scenes in C++ to: > > > > setObject(NullPtr); > > > > where "NullPtr" is a global const value defined by the library that is > > used to signify a NULL shared pointer throughout the system. (the > > reason it needs something like this is a little complex, but it is not > > my library so I can't change this part much.) > > > > Alternatively, I could probably make it work if I could get > > boost.python to make a call like: > > > > setObject(ref_ptr(NULL) ) > > > > as I think I could get the library to automatically convert > > ref_ptr(NULL) into a NullPtr. > > > > Any ideas? > > I think you can do either version by registering your own rvalue > from_python converters for all your pointer types. You can do this in > the def_visitor along with the to_python conversion we discussed earlier. > > Just replace the relevant bits below ("Deal with the "None" case") with > whatever you want. I am sorting through this code right now. Am I missing something or is there no documentation in the reference guide about how to register a converter directly with the registry? Additionally, I was looking at the documentation for implicitly_convertible and I am wondering why I can't just use that in my case. I want to call: setObject(ptr val) with a NoneType. And I have all my objects (ie. Base) wrapped and set with held types of ref_ptr<>'s. RefPtr's are implicitly convertible to ptr<>'s, so If I register this with boost.python using: bp::implicitly_convertible< ret_ptr, ptr >(); Then shouldn't boost.python be able to convert NoneType --> ref_ptr --> ptr ? From the documentation in implicitly_convertible it seems like this should be the case. But I have to admit I have not found the place in the boost.python code where it handles the case of taking a NoneType and automatically converting it into a NULL smart pointer to start with. -Allen > > Again, I'm just typing this so it may not compile, and no guarantees of > course... > > template > struct smart_ptr_from_python { > typedef typename boost::python::pointee::type Pointee; > smart_ptr_from_python() { > converter::registry::insert(&convertible, &construct, > type_id()); > } > private: > static void *convertible(PyObject *p) { > // can always produce a pointer from None. > if (p == Py_None) > return p; > // Otherwise, we can do it if we can get the pointee out. > void *result = converter::get_lvalue_from_python > (p, converter::registered::converters); > return result; > } > > static void construct(PyObject* source, converter:: > rvalue_from_python_stage1_data* data) { > void* const storage = > ((converter::rvalue_from_python_storage*)data)-> > storage.bytes; > // Deal with the "None" case. > if (data->convertible == source) > new (storage) Ptr(); // Or whatever you want. > else > new (storage) > Ptr(static_cast(data->convertible)); > data->convertible = storage; > } > }; > > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From kir at lapshin.net Wed Sep 6 21:20:02 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Wed, 06 Sep 2006 23:20:02 +0400 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> Message-ID: Roman Yakovenko wrote: >> struct Foo >> { >> enum Bar {BAR1, BAR2}; >> >> explicit Foo(Bar arg = BAR1); >> }; >> >> >> Py++ generates code that tries to add constructor (and default argument) >> prior to enum being registered. Result is exception in module import. >> >> Any ideas how to fix / work around? Other then moving enum outside the >> class? > > mb = module_builder_t( ... ) > Foo = mb.constructor( 'Foo' ) #I assume that there is only one constructor > Foo.arguments[0].default_value = 'int(%s)' % Foo.arguments[0].default_value > Oh, I see. But that would only work for enums, wouldn't it? I would prefer some more generic solution. In fact I've already encountered another similar problem. This time it is more along the lines of: struct Foo { explicit Foo( const shared_ptr& foo = shared_ptr() ); }; > You are not the first one who has this problem. Another work around is: > using boost::python; > class_< Foo > foo( "Foo", no_init ); > scope foo_scope( foo ); > enum_< ... >...; > foo_scope.def( init< ... >( ... ) ); That makes a lot of sense, but that requires modification of Py++, doesn't it? Or is there a way to customize code generation to do it the way you've cited? Seems to me if Py++ would always opt for code like that, it would already solve quite a few dependency problems. I would be more then happy to implement this. Could you point me in right direction, please? > If you search this mailing list you will find few discussions about > this problem. > I hope I will be able to submit patch to the library that will solve "default > arguments" dependency problem. Yep, I've found few messages. Looks like you are planning to patch boost.python. That would be the ultimate solution! Though it is a long term solution, and we also need something in short/mid term... Kirill From roman.yakovenko at gmail.com Wed Sep 6 21:31:32 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Wed, 6 Sep 2006 22:31:32 +0300 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> Message-ID: <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> On 9/6/06, Kirill Lapshin wrote: > Oh, I see. But that would only work for enums, wouldn't it? I would > prefer some more generic solution. In fact I've already encountered > another similar problem. This time it is more along the lines of: > > struct Foo > { > explicit Foo( const shared_ptr& foo = shared_ptr() ); > }; > > > > You are not the first one who has this problem. Another work around is: > > using boost::python; > > class_< Foo > foo( "Foo", no_init ); > > scope foo_scope( foo ); > > enum_< ... >...; > > foo_scope.def( init< ... >( ... ) ); > > That makes a lot of sense, but that requires modification of Py++, > doesn't it? Or is there a way to customize code generation to do it the > way you've cited? > > Seems to me if Py++ would always opt for code like that, it would > already solve quite a few dependency problems. > > I would be more then happy to implement this. Could you point me in > right direction, please? Yes of course: code_creators\class_declaration.py - class_t._generate_constructor It should not be too difficult to change the code. Next document will help you to understand design\architecture of Py++ http://language-binding.net/pyplusplus/documentation/architecture.html -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From amohr at pixar.com Wed Sep 6 22:35:34 2006 From: amohr at pixar.com (Alex Mohr) Date: Wed, 06 Sep 2006 13:35:34 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: <44FF3116.8070504@pixar.com> > I am sorting through this code right now. Am I missing something or > is there no documentation in the reference guide about how to register > a converter directly with the registry? No, but the code I posted does it in the constructor. > Additionally, I was looking at the documentation for > implicitly_convertible and I am wondering why I can't just use that in > my case. > > I want to call: > > setObject(ptr val) > > with a NoneType. And I have all my objects (ie. Base) wrapped and set > with held types of ref_ptr<>'s. RefPtr's are implicitly convertible > to ptr<>'s, so If I register this with boost.python using: > > bp::implicitly_convertible< ret_ptr, ptr >(); > > Then shouldn't boost.python be able to convert NoneType --> > ref_ptr --> ptr ? From the documentation in > implicitly_convertible it seems like this should be the case. But I > have to admit I have not found the place in the boost.python code > where it handles the case of taking a NoneType and automatically > converting it into a NULL smart pointer to start with. Sure -- if your types meet those requirements, then that should work. The rvalue converters I posted are more general. implicitly_convertible just registers an rvalue converter using the same underlying mechanism. From your message, I was under the impression that default-constructing one of your smart pointers would not produce the desired "null" value. Alex From abierbaum at gmail.com Wed Sep 6 22:50:56 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 15:50:56 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FF3116.8070504@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3116.8070504@pixar.com> Message-ID: On 9/6/06, Alex Mohr wrote: > > I am sorting through this code right now. Am I missing something or > > is there no documentation in the reference guide about how to register > > a converter directly with the registry? > > No, but the code I posted does it in the constructor. > > > Additionally, I was looking at the documentation for > > implicitly_convertible and I am wondering why I can't just use that in > > my case. > > > > I want to call: > > > > setObject(ptr val) > > > > with a NoneType. And I have all my objects (ie. Base) wrapped and set > > with held types of ref_ptr<>'s. RefPtr's are implicitly convertible > > to ptr<>'s, so If I register this with boost.python using: > > > > bp::implicitly_convertible< ret_ptr, ptr >(); > > > > Then shouldn't boost.python be able to convert NoneType --> > > ref_ptr --> ptr ? From the documentation in > > implicitly_convertible it seems like this should be the case. But I > > have to admit I have not found the place in the boost.python code > > where it handles the case of taking a NoneType and automatically > > converting it into a NULL smart pointer to start with. > > Sure -- if your types meet those requirements, then that should work. > The rvalue converters I posted are more general. implicitly_convertible > just registers an rvalue converter using the same underlying mechanism. > > From your message, I was under the impression that default-constructing > one of your smart pointers would not produce the desired "null" value. A default construction of the RefPtr Type should, but using implicitly_convertible didn't work. It acted like it didn't know that there was an option to convert through the implicit chains. I have now implemented something based on the code you posted and am working on testing it. Hopefully it will work out. I will let you kno. -Allen > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From abierbaum at gmail.com Wed Sep 6 23:06:42 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 16:06:42 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FE0AB2.8010006@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: On 9/5/06, Alex Mohr wrote: > > Thanks Alex, this worked great. I had to change the Py_INCREF to a > > bp::incref but otherwise things are all good. > > > > But now I have a rather strange followup question. > > > > It seems that Boost.Python is doing some magic behind the scenes to > > convert an object coming from C++ as a smart pointer whose wrapped > > pointer is NULL into a Python "None". The is great, and was a > > wonderful surprise. But now I need to find a way to make it happen in > > the other direction. > > > > How does boost.python convert a parameter of "None" into an > > object/smart_ptr to pass to C++? > > It happens in the from_python conversion. It just checks for None and > (I believe) default-constructs a the pointer object. Is it the case > that default-constructing one of your smart pointers does not produce > the intended NULL? It probably wouldn't be hard to add a customization > (paralleling get_pointer and pointee) to boost python. But in the > meantime... > > > I need to find a way to call a C++ method like: > > > > void setObject(ptr obj); > > > > from Python and call it in Python as "setObject(None)" and instruct > > boost.python to convert this into a call behind the scenes in C++ to: > > > > setObject(NullPtr); > > > > where "NullPtr" is a global const value defined by the library that is > > used to signify a NULL shared pointer throughout the system. (the > > reason it needs something like this is a little complex, but it is not > > my library so I can't change this part much.) > > > > Alternatively, I could probably make it work if I could get > > boost.python to make a call like: > > > > setObject(ref_ptr(NULL) ) > > > > as I think I could get the library to automatically convert > > ref_ptr(NULL) into a NullPtr. > > > > Any ideas? > > I think you can do either version by registering your own rvalue > from_python converters for all your pointer types. You can do this in > the def_visitor along with the to_python conversion we discussed earlier. > > Just replace the relevant bits below ("Deal with the "None" case") with > whatever you want. > > Again, I'm just typing this so it may not compile, and no guarantees of > course... > > template > struct smart_ptr_from_python { > typedef typename boost::python::pointee::type Pointee; > smart_ptr_from_python() { > converter::registry::insert(&convertible, &construct, > type_id()); > } > private: > static void *convertible(PyObject *p) { > // can always produce a pointer from None. > if (p == Py_None) > return p; > // Otherwise, we can do it if we can get the pointee out. > void *result = converter::get_lvalue_from_python > (p, converter::registered::converters); > return result; > } > > static void construct(PyObject* source, converter:: > rvalue_from_python_stage1_data* data) { > void* const storage = > ((converter::rvalue_from_python_storage*)data)-> > storage.bytes; > // Deal with the "None" case. > if (data->convertible == source) > new (storage) Ptr(); // Or whatever you want. > else > new (storage) > Ptr(static_cast(data->convertible)); > data->convertible = storage; > } > }; This code allowed the setObject(None) to work now. Unfortunately it broke the functionality that had been working where I could call setObject(PythonObject). More details (extracted from above): I have: // set method void setObject(ptr obj); // Implicit conversion for ref_ptr to ptr bp::implicitly_convertible< ref_ptr, ptr ); // From original e-mail: this works to automatically convert // ptr returns into ref_ptr as the held type bp::to_pyton_converter< ptr, ptr_to_python< ptr >() // Most recent discussion: way to get None from python as ptr // - This works to let me pass None into wrapped setObject method bp::converter::registry::insert(&convertible, &construct, bp::type_id >()); The problem is that now when I try to call something like this in python: new_obj = objtype.create() setObject(None) setObject(new_obj) Both of these calls to setObject try to convert the object to a ptr using the manually registered converter. The converter only really knows how to deal with the conversion from a None type. In the case of a real object I just want boost.python to convert the held type (ref_ptr ) into a ptr using the implicit conversion. How do I get this to work? Can I have multiple converters registered and if so how do I tell boost.python to only use the manually created one for the NoneType? -Allen From amohr at pixar.com Wed Sep 6 23:19:43 2006 From: amohr at pixar.com (Alex Mohr) Date: Wed, 06 Sep 2006 14:19:43 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> Message-ID: <44FF3B6F.9030509@pixar.com> > This code allowed the setObject(None) to work now. Unfortunately it > broke the functionality that had been working where I could call > setObject(PythonObject). > > More details (extracted from above): > > I have: > > // set method > void setObject(ptr obj); > > // Implicit conversion for ref_ptr to ptr > bp::implicitly_convertible< ref_ptr, ptr ); > > // From original e-mail: this works to automatically convert > // ptr returns into ref_ptr as the held type > bp::to_pyton_converter< ptr, ptr_to_python< ptr >() > > // Most recent discussion: way to get None from python as ptr > // - This works to let me pass None into wrapped setObject method > bp::converter::registry::insert(&convertible, &construct, > bp::type_id >()); > > The problem is that now when I try to call something like this in python: > > new_obj = objtype.create() > setObject(None) > setObject(new_obj) > > Both of these calls to setObject try to convert the object to a > ptr using the manually registered converter. The converter only > really knows how to deal with the conversion from a None type. In the > case of a real object I just want boost.python to convert the held > type (ref_ptr ) into a ptr using the implicit conversion. > > How do I get this to work? Can I have multiple converters registered > and if so how do I tell boost.python to only use the manually created > one for the NoneType? The rvalue converter should handle both cases. In convertible, it checks if it is getting None -- if it is, it says yes, I can make a pointer. If it gets something other than None, it says I can make a pointer iff I can get an lvalue pointer to the Pointee from the python object. That's the code after the if. It uses already registered lvalue converters to do this. The construct method has a similar structure -- in the None case (first part of if) it will just placement new a default-constructed pointer. In the else part of the if, it will placement new a pointer pointing to the c++ instance. Can you tell me what's going on in convertible and construct when you do this? > setObject(new_obj) Alex >> template >> struct smart_ptr_from_python { >> typedef typename boost::python::pointee::type Pointee; >> smart_ptr_from_python() { >> converter::registry::insert(&convertible, &construct, >> type_id()); >> } >> private: >> static void *convertible(PyObject *p) { >> // can always produce a pointer from None. >> if (p == Py_None) >> return p; >> // Otherwise, we can do it if we can get the pointee out. >> void *result = converter::get_lvalue_from_python >> (p, converter::registered::converters); >> return result; >> } >> >> static void construct(PyObject* source, converter:: >> rvalue_from_python_stage1_data* data) { >> void* const storage = >> ((converter::rvalue_from_python_storage*)data)-> >> storage.bytes; >> // Deal with the "None" case. >> if (data->convertible == source) >> new (storage) Ptr(); // Or whatever you want. >> else >> new (storage) >> Ptr(static_cast(data->convertible)); >> data->convertible = storage; >> } >> }; From abierbaum at gmail.com Wed Sep 6 23:32:12 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 16:32:12 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FF3B6F.9030509@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> Message-ID: On 9/6/06, Alex Mohr wrote: > > This code allowed the setObject(None) to work now. Unfortunately it > > broke the functionality that had been working where I could call > > setObject(PythonObject). > > > > More details (extracted from above): > > > > I have: > > > > // set method > > void setObject(ptr obj); > > > > // Implicit conversion for ref_ptr to ptr > > bp::implicitly_convertible< ref_ptr, ptr ); > > > > // From original e-mail: this works to automatically convert > > // ptr returns into ref_ptr as the held type > > bp::to_pyton_converter< ptr, ptr_to_python< ptr >() > > > > // Most recent discussion: way to get None from python as ptr > > // - This works to let me pass None into wrapped setObject method > > bp::converter::registry::insert(&convertible, &construct, > > bp::type_id >()); > > > > The problem is that now when I try to call something like this in python: > > > > new_obj = objtype.create() > > setObject(None) > > setObject(new_obj) > > > > Both of these calls to setObject try to convert the object to a > > ptr using the manually registered converter. The converter only > > really knows how to deal with the conversion from a None type. In the > > case of a real object I just want boost.python to convert the held > > type (ref_ptr ) into a ptr using the implicit conversion. > > > > How do I get this to work? Can I have multiple converters registered > > and if so how do I tell boost.python to only use the manually created > > one for the NoneType? > > > The rvalue converter should handle both cases. In convertible, it > checks if it is getting None -- if it is, it says yes, I can make a > pointer. If it gets something other than None, it says I can make a > pointer iff I can get an lvalue pointer to the Pointee from the python > object. That's the code after the if. It uses already registered > lvalue converters to do this. > > The construct method has a similar structure -- in the None case (first > part of if) it will just placement new a default-constructed pointer. > In the else part of the if, it will placement new a pointer pointing to > the c++ instance. > > Can you tell me what's going on in convertible and construct when you do > this? The problem for me was that the rvalue converter when passed a non-None could not do the placement new created of the ptr because the constructor is protected. The library I am wrapping requires all objects to be created using static factory methods: ref_ptr obj = Class.create() So there is something going on in the implicit conversion for the smart pointers that just handles things better. I ended up getting the code to work though by making it so the rvalue convertible method return NULL if p != NonType. This ends up meaning that the rvalue converter is only used in the case of passing None, but it works for me now. Thanks for your help. I will let you know if anything else crops up but I think I am starting to understand this part of boost.python much better now so hopefully I will be able to fix it myself. :) Thanks, Allen > > > setObject(new_obj) > > Alex > > > >> template > >> struct smart_ptr_from_python { > >> typedef typename boost::python::pointee::type Pointee; > >> smart_ptr_from_python() { > >> converter::registry::insert(&convertible, &construct, > >> type_id()); > >> } > >> private: > >> static void *convertible(PyObject *p) { > >> // can always produce a pointer from None. > >> if (p == Py_None) > >> return p; > >> // Otherwise, we can do it if we can get the pointee out. > >> void *result = converter::get_lvalue_from_python > >> (p, converter::registered::converters); > >> return result; > >> } > >> > >> static void construct(PyObject* source, converter:: > >> rvalue_from_python_stage1_data* data) { > >> void* const storage = > >> ((converter::rvalue_from_python_storage*)data)-> > >> storage.bytes; > >> // Deal with the "None" case. > >> if (data->convertible == source) > >> new (storage) Ptr(); // Or whatever you want. > >> else > >> new (storage) > >> Ptr(static_cast(data->convertible)); > >> data->convertible = storage; > >> } > >> }; > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From amohr at pixar.com Wed Sep 6 23:45:10 2006 From: amohr at pixar.com (Alex Mohr) Date: Wed, 06 Sep 2006 14:45:10 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> Message-ID: <44FF4166.7040404@pixar.com> > The problem for me was that the rvalue converter when passed a > non-None could not do the placement new created of the ptr > because the constructor is protected. The library I am wrapping > requires all objects to be created using static factory methods: > > ref_ptr obj = Class.create() But the converter's not trying to create a new *object* -- just a new smart pointer. If you can write code that obtains a correct new smart pointer from a raw object pointer, then just fill in that code in the right place in the converter and it should work. The only other thing that's required is that the smart pointer objects be copy-constructible, which I would think they ought to be. Otherwise they're very strange. > So there is something going on in the implicit conversion for the > smart pointers that just handles things better. > > I ended up getting the code to work though by making it so the rvalue > convertible method return NULL if p != NonType. This ends up meaning > that the rvalue converter is only used in the case of passing None, > but it works for me now. Sure -- that sounds like it will be okay given your situation. > Thanks for your help. I will let you know if anything else crops up > but I think I am starting to understand this part of boost.python much > better now so hopefully I will be able to fix it myself. :) No problem. Alex From abierbaum at gmail.com Thu Sep 7 00:09:09 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Wed, 6 Sep 2006 17:09:09 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <44FF4166.7040404@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <44FF4166.7040404@pixar.com> Message-ID: On 9/6/06, Alex Mohr wrote: > > The problem for me was that the rvalue converter when passed a > > non-None could not do the placement new created of the ptr > > because the constructor is protected. The library I am wrapping > > requires all objects to be created using static factory methods: > > > > ref_ptr obj = Class.create() > > But the converter's not trying to create a new *object* -- just a new > smart pointer. If you can write code that obtains a correct new smart > pointer from a raw object pointer, then just fill in that code in the > right place in the converter and it should work. This is the part I can't do. I can make a ref_ptr<> from a ptr<> as vice versa, but I can't build either of them from a raw pointer. I may take a look at this later and see if I can make it work better so I just have the one converter. > The only other thing > that's required is that the smart pointer objects be copy-constructible, > which I would think they ought to be. Otherwise they're very strange. > > > So there is something going on in the implicit conversion for the > > smart pointers that just handles things better. > > > > I ended up getting the code to work though by making it so the rvalue > > convertible method return NULL if p != NonType. This ends up meaning > > that the rvalue converter is only used in the case of passing None, > > but it works for me now. > > Sure -- that sounds like it will be okay given your situation. I agree. NoneType --> ptr<> was always a special case for me since I want everything held by ref_ptrs all the time anyway. Thanks again. -Allen > > > Thanks for your help. I will let you know if anything else crops up > > but I think I am starting to understand this part of boost.python much > > better now so hopefully I will be able to fix it myself. :) > > No problem. > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From kir at lapshin.net Thu Sep 7 12:04:19 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Thu, 07 Sep 2006 14:04:19 +0400 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> Message-ID: Roman Yakovenko wrote: >> I would be more then happy to implement this. Could you point me in >> right direction, please? > > Yes of course: > > code_creators\class_declaration.py - class_t._generate_constructor > It should not be too difficult to change the code. > > Next document will help you to understand design\architecture of Py++ > http://language-binding.net/pyplusplus/documentation/architecture.html Thanks. Will take a look. Unfortunately I have to postpone it for a bit. It turns out the problem I have is a bit different, and at the moment the highest priority task is get the bindings working, I will try to make them nicer next. The problem I have at the moment is along the lines of: struct Base {}; struct Derived: public Base { Derived(const vector >& arg = vector >() ); }; What happens is in mymodule.main.cpp vector > gets registered after both Base and Derived, and obviously registration of Derived fails. Is there any way to change the order in which various classes get registered? Kirill From ndbecker2 at gmail.com Thu Sep 7 16:17:18 2006 From: ndbecker2 at gmail.com (Neal Becker) Date: Thu, 07 Sep 2006 10:17:18 -0400 Subject: [C++-sig] boost::python tutorial on overloading not up-to-date? Message-ID: In boost::python tutorial there is a whole section on manual overloading. AFAICT, overloading "just works" without my doing anything. Is this information out-of-date? From abierbaum at gmail.com Thu Sep 7 17:09:52 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Thu, 7 Sep 2006 10:09:52 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> Message-ID: > > Thanks for your help. I will let you know if anything else crops up > but I think I am starting to understand this part of boost.python much > better now so hopefully I will be able to fix it myself. :) It looks like everything related to the auto-converting to ref_ptr held type and handling of converting to and from None. I have one remaining problem that I know of with this code. How do I make it possible to compare the wrapped ref_ptrs for equality? I am assuming that I need to add an __eq__ operator for the ref_ptr types but since they are used as held_type I am not really exposing them in the "normal" way. This is how it is behaving right now (note: all the objects here have ref_ptr held type) >> n = osg.Node.create() >> g = osg.Group.create() >> n.setCore(g) >> g >> n.getCore() >> g == n.getCore() False Does anyone know if this is also an issue when wrapping an API and using boost::shared_ptr<> as the held type? If so, how is that case handled? Thanks, Allen From amohr at pixar.com Thu Sep 7 18:39:18 2006 From: amohr at pixar.com (Alex Mohr) Date: Thu, 07 Sep 2006 09:39:18 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> Message-ID: <45004B36.1020800@pixar.com> > I have one remaining problem that I know of with this code. How do I > make it possible to compare the wrapped ref_ptrs for equality? I am > assuming that I need to add an __eq__ operator for the ref_ptr types > but since they are used as held_type I am not really exposing them in > the "normal" way. Yup -- you'll have to implement __eq__. > >>> n.getCore() > >>> g == n.getCore() > False > > Does anyone know if this is also an issue when wrapping an API and > using boost::shared_ptr<> as the held type? If so, how is that case > handled? It works sometimes, and not others. As you discovered, boost python will store the python object in a custom shared_ptr deleter. Converting to-python, I believe it will see if the shared_ptr has its custom deleter and will use the python object in there if it is. The problem is that if you're using your own shared_ptrs, then you may pass a shared_ptr to boost python which doesn't have the special custom deleter, and you'll end up with multiple python objects representing the same c++ object. What you really want is to have just a single python object associated with each C++ instance. I call this problem "object identity", and it's been discussed on this list before. It is *possible* to solve this problem with boost python as is, but it requires doing *very* nasty things using internal api. I think the real solution is to extend boost python so that: - You can tell boost python that your c++ object can manage its python identity. - As soon as boost python produces a python object for your c++ object, it calls you to establish the identity. - Whenever (a pointer to) that c++ instance is to be converted to-python, boost python will consult you to find the python object. Incidentally, wrapper already does this stuff mostly right. I hope to make a patch to support this someday, but it probably won't be that soon. Anyway, in the meantime, if you just implement __eq__ in the obvious way, it should work. Alex From abierbaum at gmail.com Thu Sep 7 18:46:37 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Thu, 7 Sep 2006 11:46:37 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <45004B36.1020800@pixar.com> References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <45004B36.1020800@pixar.com> Message-ID: On 9/7/06, Alex Mohr wrote: > > I have one remaining problem that I know of with this code. How do I > > make it possible to compare the wrapped ref_ptrs for equality? I am > > assuming that I need to add an __eq__ operator for the ref_ptr types > > but since they are used as held_type I am not really exposing them in > > the "normal" way. > > Yup -- you'll have to implement __eq__. > > > > >>> n.getCore() > > > >>> g == n.getCore() > > False > > > > Does anyone know if this is also an issue when wrapping an API and > > using boost::shared_ptr<> as the held type? If so, how is that case > > handled? > > It works sometimes, and not others. As you discovered, boost python > will store the python object in a custom shared_ptr deleter. Converting > to-python, I believe it will see if the shared_ptr has its custom > deleter and will use the python object in there if it is. > > The problem is that if you're using your own shared_ptrs, then you may > pass a shared_ptr to boost python which doesn't have the special custom > deleter, and you'll end up with multiple python objects representing the > same c++ object. > > What you really want is to have just a single python object associated > with each C++ instance. > > I call this problem "object identity", and it's been discussed on this > list before. > > It is *possible* to solve this problem with boost python as is, but it > requires doing *very* nasty things using internal api. > > I think the real solution is to extend boost python so that: > > - You can tell boost python that your c++ object can manage its python > identity. > > - As soon as boost python produces a python object for your c++ object, > it calls you to establish the identity. > > - Whenever (a pointer to) that c++ instance is to be converted > to-python, boost python will consult you to find the python object. > > Incidentally, wrapper already does this stuff mostly right. I hope > to make a patch to support this someday, but it probably won't be that soon. > > Anyway, in the meantime, if you just implement __eq__ in the obvious > way, it should work. The non-obvious part of this for me is: - Does this mean that I now need to explicitly wrap (expose using bp::class_ ) all the ref_ptr<> types? I haven't had to do that thus far because it was handled internally somehow because I used it has the held_type for all my classes. If I expose them manually do I run the risk of breaking any of the held_type functionality? -Allen From amohr at pixar.com Thu Sep 7 18:55:05 2006 From: amohr at pixar.com (Alex Mohr) Date: Thu, 07 Sep 2006 09:55:05 -0700 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44F5CD10.5010103@pixar.com> <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <45004B36.1020800@pixar.com> Message-ID: <45004EE9.7040604@pixar.com> > The non-obvious part of this for me is: > > - Does this mean that I now need to explicitly wrap (expose using > bp::class_ ) all the ref_ptr<> types? > > I haven't had to do that thus far because it was handled internally > somehow because I used it has the held_type for all my classes. If I > expose them manually do I run the risk of breaking any of the > held_type functionality? I'm not sure what you mean... If ref_ptr is the held type for T, then just provide __eq__ in terms of ref_ptr... template static bool ref_ptr_eq(ref_ptr const &self, ref_ptr const &other) { return self == other; } class_ ... >(...) .def("__eq__", ref_ptr_eq) ; Am I misunderstanding your situation? Alex From roman.yakovenko at gmail.com Thu Sep 7 19:54:29 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Thu, 7 Sep 2006 20:54:29 +0300 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> Message-ID: <7465b6170609071054k49eb0cb0x53e243ee330fffec@mail.gmail.com> On 9/7/06, Kirill Lapshin wrote: > Roman Yakovenko wrote: > >> I would be more then happy to implement this. Could you point me in > >> right direction, please? > > > > Yes of course: > > > > code_creators\class_declaration.py - class_t._generate_constructor > > It should not be too difficult to change the code. > > > > Next document will help you to understand design\architecture of Py++ > > http://language-binding.net/pyplusplus/documentation/architecture.html > > Thanks. Will take a look. Unfortunately I have to postpone it for a bit. > It turns out the problem I have is a bit different, and at the moment > the highest priority task is get the bindings working, I will try to > make them nicer next. > > The problem I have at the moment is along the lines of: > > struct Base {}; > > struct Derived: public Base > { > Derived(const vector >& arg = > vector >() ); > }; > > What happens is in mymodule.main.cpp vector > gets > registered after both Base and Derived, and obviously registration of > Derived fails. > > Is there any way to change the order in which various classes get > registered? Yes of course. Take a look on this example( unit test ): http://svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/unittests/class_order_tester.py?view=markup Then you can take a look on code_creators: compound_t, module_t, module_body_t. This should help you. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From abierbaum at gmail.com Thu Sep 7 20:32:45 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Thu, 7 Sep 2006 13:32:45 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: <45004EE9.7040604@pixar.com> References: <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <45004B36.1020800@pixar.com> <45004EE9.7040604@pixar.com> Message-ID: On 9/7/06, Alex Mohr wrote: > > The non-obvious part of this for me is: > > > > - Does this mean that I now need to explicitly wrap (expose using > > bp::class_ ) all the ref_ptr<> types? > > > > I haven't had to do that thus far because it was handled internally > > somehow because I used it has the held_type for all my classes. If I > > expose them manually do I run the risk of breaking any of the > > held_type functionality? > > I'm not sure what you mean... If ref_ptr is the held type for T, > then just provide __eq__ in terms of ref_ptr... > > template > static bool ref_ptr_eq(ref_ptr const &self, ref_ptr const &other) > { > return self == other; > } > > class_ ... >(...) > .def("__eq__", ref_ptr_eq) > ; > > Am I misunderstanding your situation? Ahhh.... No I see what you are meaning. So I need the __eq__ op on the class itself. Ok. That makes more sense. I thought I may have to wrap the ref_ptr as a class a and put the __eq__ op on it. Something like: class_, ..>(..) .def("__eq__", ref_ptr_eq) ; Thanks for the feedback. I will try your method out and reply to the list with the results so other people following along can see what ended up working. Thanks again, Allen > > Alex > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From kir at lapshin.net Thu Sep 7 21:09:20 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Thu, 07 Sep 2006 23:09:20 +0400 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: <7465b6170609071054k49eb0cb0x53e243ee330fffec@mail.gmail.com> References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> <7465b6170609071054k49eb0cb0x53e243ee330fffec@mail.gmail.com> Message-ID: Roman Yakovenko wrote: >> Is there any way to change the order in which various classes get >> registered? > > Yes of course. Take a look on this example( unit test ): > http://svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/unittests/class_order_tester.py?view=markup > > Then you can take a look on code_creators: compound_t, module_t, > module_body_t. This should help you. Works like a charm! Thanks a bunch. There is one tiny annoyance though -- match_declaration_t can't search declarations by alias, and searching by name is not that nice, since it requires spelling out full name such as std::vector< boost::shared_ptr, std::allocator< boost::shared_ptr >. Not a big deal, I wrote my own matcher that does what I want. From roman.yakovenko at gmail.com Thu Sep 7 21:22:39 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Thu, 7 Sep 2006 22:22:39 +0300 Subject: [C++-sig] [Py++] Nested enum as default arg In-Reply-To: References: <7465b6170609051100x745f016fxde34980bc7021767@mail.gmail.com> <7465b6170609061231s113a1440h8d435e861621a540@mail.gmail.com> <7465b6170609071054k49eb0cb0x53e243ee330fffec@mail.gmail.com> Message-ID: <7465b6170609071222ob4cd8b3w53135eb4cdc0fed2@mail.gmail.com> On 9/7/06, Kirill Lapshin wrote: > Roman Yakovenko wrote: > >> Is there any way to change the order in which various classes get > >> registered? > > > > Yes of course. Take a look on this example( unit test ): > > http://svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/unittests/class_order_tester.py?view=markup > > > > Then you can take a look on code_creators: compound_t, module_t, > > module_body_t. This should help you. > > Works like a charm! Thanks a bunch. Enjoy. > There is one tiny annoyance though -- match_declaration_t can't search > declarations by alias, and searching by name is not that nice, since it > requires spelling out full name such as std::vector< > boost::shared_ptr, std::allocator< boost::shared_ptr >. > Not a big deal, I wrote my own matcher that does what I want. Someday "code creators tree" will provide better( more user friendly ) interface. It will happen, I am sure. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From kir at lapshin.net Thu Sep 7 21:37:36 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Thu, 07 Sep 2006 23:37:36 +0400 Subject: [C++-sig] [boost.python] Indexing suite problems with convertable element type Message-ID: Hi, I am just making my first step in boost.python world, so please forgive me for potential FAQ, but I can't find an answer in docs and by googling. I have a custom date class, that I registered for conversion to Python's datetime.date object. Individual dates convert fine, but when I registered vector with indexing suite, I have a problem that I can insert python date objects into vector, but can't extract them. E.g. >>> v = vector_day() >>> v.append( datetime.date(2006,1,1) ) >>> len(v) 1 >>> v[0] Traceback (most recent call last): File "", line 1, in ? TypeError: No Python class registered for C++ class class day vector_day is exposed like this: bp::class_< std::vector > >( "vector_day" ) .def( bp::vector_indexing_suite< ::std::vector > >() ); As I said, individual date objects convert just fine back and forth, i.e. function day test_day( day x ) { return x+1; } exposed as typedef day ( *function_ptr_t )( day ); bp::def( "test_day", function_ptr_t( &test_day ), ( bp::arg("x") ), bp::default_call_policies() ); can be used from Python without problems: >>> test_day( datetime.date(2006,1,1) ) datetime.date(2006, 1, 2) What am I doing wrong? Regards, Kirill Lapshin From kir at lapshin.net Thu Sep 7 21:52:48 2006 From: kir at lapshin.net (Kirill Lapshin) Date: Thu, 07 Sep 2006 23:52:48 +0400 Subject: [C++-sig] [boost.python] Indexing suite problems with convertable element type In-Reply-To: References: Message-ID: > I have a custom date class, that I registered for conversion to Python's > datetime.date object. Individual dates convert fine, but when I > registered vector with indexing suite, I have a problem that I can > insert python date objects into vector, but can't extract them. Nevermind. A bit more searching around and I found this thread: http://thread.gmane.org/gmane.comp.python.c++/9846/focus=9846 So it can be solved by setting NoProxy to true. Now I just have to figure out how to instruct Py++ to set NoProxy... From roman.yakovenko at gmail.com Thu Sep 7 21:59:18 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Thu, 7 Sep 2006 22:59:18 +0300 Subject: [C++-sig] [boost.python] Indexing suite problems with convertable element type In-Reply-To: References: Message-ID: <7465b6170609071259m90d780cn14adcdb992a02285@mail.gmail.com> On 9/7/06, Kirill Lapshin wrote: > > I have a custom date class, that I registered for conversion to Python's > > datetime.date object. Individual dates convert fine, but when I > > registered vector with indexing suite, I have a problem that I can > > insert python date objects into vector, but can't extract them. > > Nevermind. A bit more searching around and I found this thread: > http://thread.gmane.org/gmane.comp.python.c++/9846/focus=9846 > > So it can be solved by setting NoProxy to true. > > Now I just have to figure out how to instruct Py++ to set NoProxy... mb = module_builder_t( ... ) cls = mb.class_( ... ) cls.indexing_suite.no_proxy = True Take a look on container_traits: http://language-binding.net/pygccxml/apidocs/pygccxml.declarations.container_traits.vector_traits-class.html -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From abierbaum at gmail.com Thu Sep 7 22:37:34 2006 From: abierbaum at gmail.com (Allen Bierbaum) Date: Thu, 7 Sep 2006 15:37:34 -0500 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) In-Reply-To: References: <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <45004B36.1020800@pixar.com> <45004EE9.7040604@pixar.com> Message-ID: On 9/7/06, Allen Bierbaum wrote: > On 9/7/06, Alex Mohr wrote: > > > The non-obvious part of this for me is: > > > > > > - Does this mean that I now need to explicitly wrap (expose using > > > bp::class_ ) all the ref_ptr<> types? > > > > > > I haven't had to do that thus far because it was handled internally > > > somehow because I used it has the held_type for all my classes. If I > > > expose them manually do I run the risk of breaking any of the > > > held_type functionality? > > > > I'm not sure what you mean... If ref_ptr is the held type for T, > > then just provide __eq__ in terms of ref_ptr... > > > > template > > static bool ref_ptr_eq(ref_ptr const &self, ref_ptr const &other) > > { > > return self == other; > > } > > > > class_ ... >(...) > > .def("__eq__", ref_ptr_eq) > > ; > > > > Am I misunderstanding your situation? > > Ahhh.... > > No I see what you are meaning. So I need the __eq__ op on the class > itself. Ok. That makes more sense. I thought I may have to wrap the > ref_ptr as a class a and put the __eq__ op on it. > > Something like: > > class_, ..>(..) > .def("__eq__", ref_ptr_eq) > ; > > Thanks for the feedback. I will try your method out and reply to the > list with the results so other people following along can see what > ended up working. (I apologize for the length of this e-mail, I just want to make sure I describe everything in case there is something basic I am missing) This did not work out well. It still has major problems because: - Object allocated in python, passed to C++, and then returned from C++ can't be compared - Objects can't be compared to None anymore Here is what I have done so far, if anyone has suggestions please let me know (code generated from py++). This is a combination of all the ideas discussed in this thread. You will notice that instead of defining an __eq__ I defined __cmp__ so all the comparison operations would work. typedef ::boost::python::class_< Group_wrapper, ::boost::python::bases< ::osg::GroupBase >, OSG::GroupRefPtr, ::boost::noncopyable > Group_exposer_t; Group_exposer_t Group_exposer = Group_exposer_t( "Group", ::boost::python::no_init ); ... Group_exposer.def("__cmp__",pyopensg::cmp_ref_ptrs); Group_exposer.def("__hash__",pyopensg::hash_ref_ptr); register_fcptr_to_python::execute(); fcptr_from_python(); bp::implicitly_convertible< OSG::GroupRefPtr, OSG::GroupPtr >(); bp::implicitly_convertible< OSG::GroupRefPtr, OSG::NodeCoreRefPtr >(); } } // Helpers are attached to the mail There is also a class Node involved in the example code below. In the example I use two methods from there: void Node::setCore(ptr); ptr Node::getCore(); Here is some code that shows the problems >>> g = osg.Group.create() >>> g2 = osg.Group.create() >>> g3 = g >>> g == g2 False >>> g == g3 True >>> hash(g) 163 >>> hash(g2) 164 >>> n = osg.Node.create() >>> n.setCore(g) >>> core_g = n.getCore() >>> core_g >>> g // Next line shows problem where the object coming back // out of C++ can't be compared. It is like it thinks it has // a different type. >>> g == core_g Traceback (most recent call last): File "", line 1, in ? ArgumentError: Python argument types in Group.__cmp__(Group, Group) did not match C++ signature: __cmp__(osg::RefPtr, osg::Group> >, osg::RefPtr, osg::Group> >) // This line shows the same problem with __hash__ >>> hash(core_g) Traceback (most recent call last): File "", line 1, in ? ArgumentError: Python argument types in Group.__hash__(Group) did not match C++ signature: __hash__(osg::RefPtr, osg::Group> >) // And here is the problem comparing to None >>> g == None Traceback (most recent call last): File "", line 1, in ? ArgumentError: Python argument types in Group.__cmp__(Group, NoneType) did not match C++ signature: __cmp__(osg::RefPtr, osg::Group> >, osg::RefPtr, osg::Group> >) >>> I am at a loss to see what is causing this signature problem. I don't know of any way to ask boost.python to give me the "signature" of python object at run-time, so I can't compare this signature with the "good" signatures that work above. From what I see though they look very much the same. I am going to try to trace back through the mailing list and look for the object identity discussions you mentioned. Maybe something in those threads will provide a workaround that I can use. As always, feel free to tell me if something looks way off. Thanks, Allen -------------- next part -------------- A non-text attachment was scrubbed... Name: bp_helpers.h Type: text/x-chdr Size: 2617 bytes Desc: not available URL: From Gottfried.Ganssauge at haufe.de Fri Sep 8 13:50:44 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Fri, 8 Sep 2006 13:50:44 +0200 Subject: [C++-sig] Bug in opaque_pointer_converter and patch Message-ID: <51F4AD92DB06E9488BBC39B7B492409E027C1EB9@vg20ex1.grp.haufemg.com> While debugging a python extension I found out that a segmentation fault was produced by the python statement print type(some_opaque_pointer) After some further debugging I found out that all instances created from opaque_pointer_converter had a type object which itself didn't have a type, and this finally lead to the crash. Find attached a patch which corrects this behaviour by initialising the type object using PyType_Ready(). Cheers, Gottfried -------------- next part -------------- A non-text attachment was scrubbed... Name: type_ready.patch Type: application/octet-stream Size: 850 bytes Desc: type_ready.patch URL: From ganssauge at gmx.de Sat Sep 9 01:57:52 2006 From: ganssauge at gmx.de (=?ISO-8859-15?Q?Gottfried_Gan=DFauge?=) Date: Sat, 09 Sep 2006 01:57:52 +0200 Subject: [C++-sig] New Patch for opaque_pointer_converter Message-ID: <45020380.50906@gmx.de> Please find attached a completely new patch against the current CVS Head. This incorporates my patch from earlier today into the CVS Head. Further I implemented cross module support in so far as the converter registers itself only if not another module already has registered the same converter before. The opaque test case has been update to check for the segmentation fault mentioned in my previous post. A test case for the cross module support is included (crossmod_opaque). I also updated the documentation for opaque. I tested my patch with - GCC-4.1 running on GNU/Linux 2.6.16.21-0.13-default x86_64 - Visual-C++-6.5 running on Windows XP - Visual-C++-7.1 running on Windows XP The patch is applied by calling patch -p1 < opaque_patch in the root of the boost hierarchy. Files patched are: boost_head/boost/python/opaque_pointer_converter.hpp boost_head/libs/python/doc/v2/opaque.html boost_head/libs/python/doc/v2/opaque_pointer_converter.html boost_head/libs/python/doc/v2/reference.html boost_head/libs/python/doc/v2/return_opaque_pointer.html boost_head.orig/libs/python/test/crossmod_opaque_a.cpp boost_head/libs/python/test/crossmod_opaque_a.cpp boost_head/libs/python/test/crossmod_opaque_b.cpp boost_head/libs/python/test/crossmod_opaque.py boost_head/libs/python/test/Jamfile boost_head/libs/python/test/Jamfile.v2 boost_head/libs/python/test/opaque.py Enjoy ... Gottfried -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: opaque_patch URL: From roman.yakovenko at gmail.com Sat Sep 9 22:29:32 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Sat, 9 Sep 2006 23:29:32 +0300 Subject: [C++-sig] custom smart pointers In-Reply-To: <44FEF8F8.8080004@pixar.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <7465b6170609051303w4132f343vc24d4cfd768408ed@mail.gmail.com> <44FDDC04.3010200@pixar.com> <7465b6170609052316w887a0b5v3723de9d1833491e@mail.gmail.com> <44FEF8F8.8080004@pixar.com> Message-ID: <7465b6170609091329q19a74e78x90a9236d62d51527@mail.gmail.com> On 9/6/06, Alex Mohr wrote: > > I don't know and understand how I should do it, really :-(. > > > > Boost.Python creates new instance of shared_ptr with custom deleter. This way it > > says to shared_ptr that the object is already managed. > > I believe it's just a hack to do what I call "object identity" -- which > is just tracking the association between a C++ instance and a python > object. When converting a shared ptr to-python, boost python checks to > see if it has its special deleter, and will use that to produce the > python object rather than constructing a new one. > > This is a fragile scheme. It fails frequently for shared ptrs, as has > been discussed on this list before, and it doesn't work at all for > custom shared pointers. > > Anyway, I consider object identity to be a different issue from the one > we're currently discussing. But I do think you should address it in > py++. We can talk about that later. I am not completely understand what you are talking about ( object identity ). I will be glad to discuss it with you and add the appropriate functionality to Py++, really. > > The smart pointer, the project use, does not provide this > > functionality. More over, > > I don't understand what data->convertible will contain. > > If I recall correctly (I'm not looking at the code) data->convertible is > the result that the convertible method returned, so in this case it's a > raw pointer to the C++ instance. > > > I think I do it: > > > > register_ptr_to_python< my_smart_ptr_t< base > >(); > > register_ptr_to_python< my_smart_ptr_t< derived > >(); > > implicitly_convertible< my_smart_ptr_t< derived >, my_smart_ptr_t< base > >(); > > > > This is what yoy mean, right? > > No, these are to-python conversions. I'm talking about rvalue > from-python conversions. Have a look at the last few messages in the > concurrent thread on this list with subject "Is there a way to > automatically convert a smart_ptr to a held_type (try 2)". > > I posted a message to that thread which has some (untested) smart > pointer rvalue from-python conversion code in it. Actually -- it > probably looks something like shared_ptr_from_python. I read the thread "Is there a way to automatically convert a smart_ptr to a held_type (try 2)" and still I am not able to get to a solution :-(. I have to say that I am lost. I implemented rvalue converter, I am registering custom to_python_converter - nothing happens. I attach the minimal example. Any help is welcome. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ -------------- next part -------------- A non-text attachment was scrubbed... Name: classes.hpp Type: text/x-c++hdr Size: 1617 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: expose_classes.cpp Type: text/x-c++src Size: 4825 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: smart_ptr.h Type: text/x-chdr Size: 1843 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: test.py Type: text/x-python Size: 240 bytes Desc: not available URL: From anderslanglands at gmail.com Sun Sep 10 18:37:24 2006 From: anderslanglands at gmail.com (anders langlands) Date: Sun, 10 Sep 2006 17:37:24 +0100 Subject: [C++-sig] Possible to inspect type of a boost::python::object Message-ID: <57ffdb9c0609100937w3a144043k490470d5d82504a5@mail.gmail.com> Currently I'm using extract::check() over a bunch of different types to decide what to do with python objects. Is there any way to inspect the type directly? A -------------- next part -------------- An HTML attachment was scrubbed... URL: From Gottfried.Ganssauge at haufe.de Mon Sep 11 11:17:03 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Mon, 11 Sep 2006 11:17:03 +0200 Subject: [C++-sig] Patch for py++ Message-ID: <51F4AD92DB06E9488BBC39B7B492409E027C1F33@vg20ex1.grp.haufemg.com> I had to make the following patch to pyplusplus\code_repository\array_1.py in order to make it compile using Visual-C++ 6.5: Index: array_1.py =================================================================== --- array_1.py (Revision 494) +++ array_1.py (Arbeitskopie) @@ -28,13 +28,14 @@ inline void raise_on_out_of_range( long unsigned int size, long unsigned int index ){ - if( index < 0 || size <= index ){ + if( size <= index ){ throw std::out_of_range("index out of range"); } } template< class TItemType, long unsigned int size > struct const_array_1_t{ + typedef boost::call_traits::param_type ref; const_array_1_t( TItemType const * const data ) : m_data( data ){ @@ -47,8 +48,7 @@ return size; } - typename boost::call_traits::param_type - item_ref( long unsigned int index ) const{ + ref item_ref( long unsigned int index ) const{ raise_on_out_of_range( size, index ); return m_data[index]; } @@ -61,6 +61,7 @@ template< class TItemType, long unsigned int size > struct array_1_t{ + typedef boost::call_traits::param_type ref; array_1_t( TItemType * data ) : m_data( data ){ @@ -73,15 +74,14 @@ return size; } - typename boost::call_traits::param_type - item_ref( long unsigned int index ) const{ + ref item_ref( long unsigned int index ) const{ raise_on_out_of_range( size, index ); return m_data[index]; } void set_item( long unsigned int index - , typename boost::call_traits::param_type new_value ){ + , ref new_value ){ raise_on_out_of_range( size, index ); m_data[index] = new_value; } Cheers, Gottfried From roman.yakovenko at gmail.com Mon Sep 11 11:54:34 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Mon, 11 Sep 2006 12:54:34 +0300 Subject: [C++-sig] Patch for py++ In-Reply-To: <51F4AD92DB06E9488BBC39B7B492409E027C1F33@vg20ex1.grp.haufemg.com> References: <51F4AD92DB06E9488BBC39B7B492409E027C1F33@vg20ex1.grp.haufemg.com> Message-ID: <7465b6170609110254n69985a84n5f177305209ec94b@mail.gmail.com> On 9/11/06, Ganssauge, Gottfried wrote: > I had to make the following patch to > pyplusplus\code_repository\array_1.py in order to make it compile using > Visual-C++ 6.5: Thank you. Unfortunately I was not able to apply the patch as is. It breaks the compilation on MSVC 7.1. I reworked the patch a little. I hope it will work on your compiler too. You can find the patch here. http://svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pyplusplus/code_repository/array_1.py?view=markup Can you test it? Thanks -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From dave at boost-consulting.com Mon Sep 11 12:55:11 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 06:55:11 -0400 Subject: [C++-sig] array of strings in boost python In-Reply-To: (ctrembla@pcigeomatics.com's message of "Fri, 8 Sep 2006 16:18:53 -0400") References: Message-ID: <87k64aad0w.fsf@pereiro.luannocracy.com> The following message is a courtesy copy of an article that has been posted to gmane.comp.lib.boost.user as well. writes: > Hi, > > newbie in python and boost::python Please post Boost.Python questions to the C++-sig: http://www.boost.org/more/mailing_lists.htm#cplussig > I have a method in c++ that returns a vector of strings, how can i > expose this method in python, and how should i use it in python Sorry to turn the question around on you, but how do you /want/ to be able to use it in Python? That will determine how you should expose it. You might look into http://boost.org/libs/python/doc/v2/indexing.html#vector_indexing_suite_class to see if it meets your needs. -- Dave Abrahams Boost Consulting www.boost-consulting.com From anderslanglands at gmail.com Mon Sep 11 12:56:51 2006 From: anderslanglands at gmail.com (anders langlands) Date: Mon, 11 Sep 2006 11:56:51 +0100 Subject: [C++-sig] PyCode_New and new.code() functions Message-ID: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> Does anyone know how to use either PyCode_New or new.code()?? Specifically I want to use new.code() and new.function() to generate some python functions from strings, which I can then call in python at some later time. My trouble is I can find exactly zero documentation on the use of these functions :( Any help would be greatly appreciated. Cheers, Anders -------------- next part -------------- An HTML attachment was scrubbed... URL: From Gottfried.Ganssauge at haufe.de Mon Sep 11 12:58:24 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Mon, 11 Sep 2006 12:58:24 +0200 Subject: [C++-sig] Patch for py++ In-Reply-To: <7465b6170609110254n69985a84n5f177305209ec94b@mail.gmail.com> Message-ID: <51F4AD92DB06E9488BBC39B7B492409E027C1F67@vg20ex1.grp.haufemg.com> > -----Original Message----- > From: c++-sig-bounces at python.org > [mailto:c++-sig-bounces at python.org] On Behalf Of Roman Yakovenko > Sent: Monday, September 11, 2006 11:55 AM > To: Development of Python/C++ integration > Subject: Re: [C++-sig] Patch for py++ > > On 9/11/06, Ganssauge, Gottfried wrote: > > I had to make the following patch to > > pyplusplus\code_repository\array_1.py in order to make it compile > > using > > Visual-C++ 6.5: > > Thank you. Unfortunately I was not able to apply the patch as > is. It breaks the compilation on MSVC 7.1. I reworked the > patch a little. I hope it will work on your compiler too. > You can find the patch here. > http://svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pypl > usplus/code_repository/array_1.py?view=markup > > Can you test it? Thanks Works :-) Cheers, Gottfried > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From seefeld at sympatico.ca Mon Sep 11 13:40:59 2006 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Mon, 11 Sep 2006 07:40:59 -0400 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> Message-ID: <45054B4B.1000303@sympatico.ca> anders langlands wrote: > Does anyone know how to use either PyCode_New or new.code()?? > Specifically I > want to use new.code() and new.function() to generate some python functions > from strings, which I can then call in python at some later time. Not knowing what PyCode_New or new.code() do (do you have a pointer ?), can't you use boost::python::exec() to convert strings to executable code ? (David, http://www.boost.org/libs/python/doc/ doesn't seem to contain the 'new' documentation for exec and exec_file yet. Is that intentional ?) Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin... From anderslanglands at gmail.com Mon Sep 11 14:24:31 2006 From: anderslanglands at gmail.com (anders langlands) Date: Mon, 11 Sep 2006 13:24:31 +0100 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <45054B4B.1000303@sympatico.ca> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> Message-ID: <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> Hi Stefan, Well PyCode_New is undocumented as far as I can see, and the header doesn't even name the arguments! new.code is documented in the library reference under module new. Its documentation is equally illuminating: it simply says "An interface to PyCode_New"... boost::python::exec sounds like exactly what I want... but I can find no documentation for this either, do you have I link? Nor can I find it in any of the boost::python headers. we're using boost 1_33_1 here at the moment. A On 9/11/06, Stefan Seefeld wrote: > > anders langlands wrote: > > Does anyone know how to use either PyCode_New or new.code()?? > > Specifically I > > want to use new.code() and new.function() to generate some python > functions > > from strings, which I can then call in python at some later time. > > Not knowing what PyCode_New or new.code() do (do you have a pointer ?), > can't you use boost::python::exec() to convert strings to executable code > ? > > (David, http://www.boost.org/libs/python/doc/ doesn't seem to contain the > 'new' documentation for exec and exec_file yet. Is that intentional ?) > > Regards, > Stefan > > -- > > ...ich hab' noch einen Koffer in Berlin... > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: From seefeld at sympatico.ca Mon Sep 11 15:24:14 2006 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Mon, 11 Sep 2006 09:24:14 -0400 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> Message-ID: <4505637E.5000706@sympatico.ca> anders langlands wrote: > boost::python::exec sounds like exactly what I want... but I can find no > documentation for this either, do you have I link? Nor can I find it in any > of the boost::python headers. we're using boost 1_33_1 here at the moment. Ah, well, I added it after the 1_33_1 release. It will be included in the 1_34 release (in case that is of any help). However, the implementation is really simple, so you may as well include the code directory: namespace boost { namespace python { object exec(str string, object global, object local) { // should be 'char const *' but older python versions don't use 'const' yet. char *s = python::extract(string); PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); } } } This executes 'string' in the context of 'global' and 'local'. The latter two are (potentially empty) dictionaries. Once execution has successfully terminated, 'global' will contain whatever objects 'string' injected into them such as type definitions and other objects. You can then extract these from 'global' and call them from C++. See for example http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/exec.cpp?revision=1.5.2.1 HTH, Stefan -- ...ich hab' noch einen Koffer in Berlin... From anderslanglands at gmail.com Mon Sep 11 16:17:07 2006 From: anderslanglands at gmail.com (anders langlands) Date: Mon, 11 Sep 2006 15:17:07 +0100 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <4505637E.5000706@sympatico.ca> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> <4505637E.5000706@sympatico.ca> Message-ID: <57ffdb9c0609110717u4c7650e1m9932a033742f05d@mail.gmail.com> Thanks stefan, that does indeed look pretty simple! However, is there any way I can do this with having my own interpreter? The problem I am trying to solve is this: I have a large class library I want to bind to python. Everything in the library (Derived) is derived ultimately from a single class, Base. Now I have functions to serialize and deserialize objects to disk. The deserialize function returns a Derived object as a Base*. When this Base* is passed back to python, python doesn't know that it's actually a Derived object, and it would be nice if it did. I basically want to be able to automatically cast the Base object to whichever flavour of Derived object it actually is in python. No all my objects support the functions typeId() and typename() to get information about what they are. So the solution I've come up with is this. I just store a big dict or list in the globals which maps typeId's to functions. These functions do the conversion of the base type to the derived type and the whole thing looks something like this: ------- def castDerivedTypeA( obj ): return DerivedTypeA( obj ) def castDerivedTypeB( obj ): return DerivedTypeB( obj ) _globalCastsDict = { DerivedTypeATypeId : castDerivedTypeA, DerivedTypeBTypeId : castDerivedTypeB, } def cast( obj ): return _globalCastsDict[ obj.typeId() ]( obj ) -------- Now obviously with a large class library it's going to be tedious and error-prone to maintain all those functions etc by hand. So what I'd like is to automatically generate the code in C++ at binding time. What I'd like is to do something like: BOOST_PYTHON_MODULE( _mymodule ) { class_ >( "DerivedA" ) ; exec( "code for castDerivedA function", current_interpreter.globals(), current_interpreter.locals() ); } Is it possible to get the globals from the currently running interpreter without actually writing the interpreter executable yourself? I realise I could just write my own interpreter and all would be fine and dandy, but I'd like this to be able to work even if I'm running in the standard python interrpreter A On 9/11/06, Stefan Seefeld wrote: > > anders langlands wrote: > > > boost::python::exec sounds like exactly what I want... but I can find no > > documentation for this either, do you have I link? Nor can I find it in > any > > of the boost::python headers. we're using boost 1_33_1 here at the > moment. > > Ah, well, I added it after the 1_33_1 release. It will be included in the > 1_34 > release (in case that is of any help). > > However, the implementation is really simple, so you may as well include > the > code directory: > > > namespace boost > { > namespace python > { > object exec(str string, object global, object local) > { > // should be 'char const *' but older python versions don't use 'const' > yet. > char *s = python::extract(string); > PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), > local.ptr()); > if (!result) throw_error_already_set(); > return object(detail::new_reference(result)); > } > } > } > > This executes 'string' in the context of 'global' and 'local'. The latter > two > are (potentially empty) dictionaries. Once execution has successfully > terminated, > 'global' will contain whatever objects 'string' injected into them such as > type definitions > and other objects. You can then extract these from 'global' and call them > from C++. > See for example > > http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/exec.cpp?revision=1.5.2.1 > > HTH, > Stefan > > -- > > ...ich hab' noch einen Koffer in Berlin... > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: From seefeld at sympatico.ca Tue Sep 12 03:19:39 2006 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Mon, 11 Sep 2006 21:19:39 -0400 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <57ffdb9c0609110717u4c7650e1m9932a033742f05d@mail.gmail.com> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> <4505637E.5000706@sympatico.ca> <57ffdb9c0609110717u4c7650e1m9932a033742f05d@mail.gmail.com> Message-ID: <45060B2B.1000703@sympatico.ca> anders langlands wrote: > Thanks stefan, that does indeed look pretty simple! > > However, is there any way I can do this with having my own interpreter? > > The problem I am trying to solve is this: > > I have a large class library I want to bind to python. Everything in the > library (Derived) is derived ultimately from a single class, Base. Now I > have functions to serialize and deserialize objects to disk. The > deserialize > function returns a Derived object as a Base*. When this Base* is passed > back > to python, python doesn't know that it's actually a Derived object, and it > would be nice if it did. I basically want to be able to automatically cast > the Base object to whichever flavour of Derived object it actually is in > python. > > No all my objects support the functions typeId() and typename() to get > information about what they are. So the solution I've come up with is this. > I just store a big dict or list in the globals which maps typeId's to > functions. These functions do the conversion of the base type to the > derived > type and the whole thing looks something like this: I'm not sure I understand the purpose of your downcasting. Those derived python classes don't offer any additional attributes over what 'Base' already has, or do they ? If not, what advantage do you get from having the type names differ, instead of using your own type system (provided by 'typeId()' and 'typename()' ? If you really want to generate python types for the many C++ classes, and you can do the conversion at runtime (as opposed to compile-time), you may consider doing all of this from within a python module, by means of the 'type()' constructor. But again, I don't yet understand what you are aiming at, since that won't give you anything you couldn't get by directly querying an object's typeId(). Thanks, Stefan -- ...ich hab' noch einen Koffer in Berlin... From dave at boost-consulting.com Tue Sep 12 03:21:22 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 21:21:22 -0400 Subject: [C++-sig] Possible to inspect type of a boost::python::object References: <57ffdb9c0609100937w3a144043k490470d5d82504a5@mail.gmail.com> Message-ID: <8764ftrib1.fsf@pereiro.luannocracy.com> "anders langlands" writes: > Currently I'm using extract::check() over a bunch of different types to > decide what to do with python objects. Is there any way to inspect the type > directly? You can inspect the _Python_ type directly: x.ptr()->ob_type; or if all the types have a common C++ base class with at least one virtual function, you can write: typeid(extract(x)()) HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 03:22:58 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 21:22:58 -0400 Subject: [C++-sig] New Patch for opaque_pointer_converter References: <45020380.50906@gmx.de> Message-ID: <87zmd5q3nx.fsf@pereiro.luannocracy.com> Gottfried Gan?auge writes: > Please find attached a completely new patch against the current CVS Head. > This incorporates my patch from earlier today into the CVS Head. > Further I implemented cross module support in so far as the converter > registers itself only if not another module already has registered the > same converter before. > The opaque test case has been update to check for the segmentation fault > mentioned in my previous post. > A test case for the cross module support is included (crossmod_opaque). > > I also updated the documentation for opaque. > > I tested my patch with > - GCC-4.1 running on GNU/Linux 2.6.16.21-0.13-default x86_64 > - Visual-C++-6.5 running on Windows XP > - Visual-C++-7.1 running on Windows XP > Feel free to check it in. If it's just a bug fix, you can merge it into the release branch as well. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 03:29:58 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 21:29:58 -0400 Subject: [C++-sig] [Py++] First imressions References: <44FD9785.9000204@lapshin.net> Message-ID: <87pse1q3c9.fsf@pereiro.luannocracy.com> Kirill Lapshin writes: > 1. The way overrides are generated does not compile on MSVC8 (2005). > Looks like the problem is in conversion of return type if return type is > bool or enum. For example > > > virtual bool is_representative( ) const { > bp::override func_is_representative = this->get_override( > "is_representative" ); > return func_is_representative( ); // errors out > } > > error C2440: 'return' : cannot convert from > 'boost::python::detail::method_result' to 'bool' > No user-defined-conversion operator available that can perform this > conversion, or the operator cannot be called This is a compiler bug, which is worked around by the enclosed patch to boost/python/override.hpp: -------------- next part -------------- A non-text attachment was scrubbed... Name: override.patch Type: text/x-patch Size: 638 bytes Desc: not available URL: -------------- next part -------------- Note that your workaround would be more idiomatic if you wrote: return func_is_representative().as(); -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 03:35:20 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 21:35:20 -0400 Subject: [C++-sig] What if a Python override returns several values? References: <44FDABA2.60809@pixar.com> Message-ID: <87k649q33b.fsf@pereiro.luannocracy.com> Alex Mohr writes: >> But if I have another virtual member function "void g(int& a, int &b)" >> which returns two integers, then I'd like the Python version to take no >> arguments and return a tuple (a,b). But how does the wrapper look like >> in this case? I would have expected something like: >> >> void g(int& a, int& b) >> { >> boost::python::tuple tup = this->get_override("g")(); >> >> a = ...extract an int from tup[0]... >> b = ...extract an int from tup[1]... >> } >> >> But when I run this code I get the following error at runtime: >> >> TypeError: No registered converter was able to extract a C++ reference >> to type boost::python::tuple from this Python object of type tuple > > Not sure exactly what's going on here, but you might be able to find out > by looking at override.hpp. Look at method_result -- that's what you're > getting back from get_override. > > Off the top of my head, I think this would probably work for you: > > tuple tup = call(this->get_override("g").ptr()); > a = ...extract an int from tup[0] > b = ...extract an int from tup[1] I don't know why people always use ugly low-level interfaces when they can use beautiful high-level ones: python::tuple tup = this->get_override("g")(); a = extract(tup[0]); . . . There's almost never a reason to use call<> anymore! I should deprecate it. I'm not trying to be critical, but this really concerns me. I see this sort of thing all the time. If you could help me understand why you were moved to suggest doing it the hard way, I would appreciate it. > It's certainly not as nice as what you wrote, But it could be. :) -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 03:53:18 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 21:53:18 -0400 Subject: [C++-sig] Returning a Python object to C++ (is get_owner the right way?) References: <20060901202535.GC28064@randombit.net> Message-ID: <87ejuhq29d.fsf@pereiro.luannocracy.com> Jack Lloyd writes: > I have a scenario where I'm wrapping a virtual base class You mean a base class with virtual functions, or an abstract base class? I'm pretty sure you don't mean class a : public virtual b { ... }; That's a virtual base class. Pedantry aside... > that offers cloning (here, sending a clone message to an object > means "return a newly constructed object of whatever type you are"), > and want to inherit from that type in Python. Simply implementing > that function in Python (eg:> > class MySubclass(mylib.MyBaseClass): > def clone(self): > return MySubclass() > > led to "returning a dangling reference" errors, so I'm using the > technique Dave suggested in > http://mail.python.org/pipermail/c++-sig/2004-December/008379.html > (basically, use get_owner, get ahold of the __class__ attribute, and > call the constructor, then keep a reference to the copy-constructed > Python object around so it is not destroyed until the lifetime of the > C++ object is over, all held inside another class that simply forwards > the appropriate messages to the Python object). > > This has been working fine for me, however since get_owner is still > undocumented (AFAICT; couldn't find it anywhere in the 1.33.1 docs), > and generally the technique led to some rather ugly code, I wanted to > check and see if any new technique/method for dealing with this > situation had developed since that discussion? Not unless you're willing to change the clone member function to return shared_ptr instead of a raw pointer. It would be fairly easy to factor out most of the interesting bits of that posting into a new library component, or just put them in wrapper<>, though. I wish I had more time.... -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 05:26:05 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 23:26:05 -0400 Subject: [C++-sig] custom smart pointers References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> Message-ID: <878xkppxyq.fsf@pereiro.luannocracy.com> "Roman Yakovenko" writes: > On 8/31/06, David Abrahams wrote: >> >From this I can't understand what you're doing or what errors you're >> getting. Please do what I tell everyone to do: make a _complete_, >> _minimal_ example that reproduces your problem and post that. > > I attached 3 files. This is complete and minimal example. It's hardly minimal! A minimal example would have no "documentation" strings, no use of named arguments (bp::arg(...)) and no use of things that you get by default anyway, like default_call_policies. It would not contain extraneous implicit conversions from int. This is a problem with many code generators: they create an unreadable mess for anyone who wants to understand the result. Part of the reason many people despise the MFC Wizards. I suggest you fix Py++ so it doesn't add vacuous "documentation" and other needless cruft. In a minimal example, there would be just one .cpp file, one .py file, and if possible, a Jamfile I can use to build and run the test. BTW, your #include guards use identifiers that are reserved to the C++ implementation. I made your example work. I had to add an operator* to your smart pointer, although I think that uncovers a bug in Boost.Python: we should be using get_pointer where it needed the operator*, instead. I don't know if this meets your needs or not, but the result is enclosed. -------------- next part -------------- A non-text attachment was scrubbed... Name: test.tar.gz Type: application/octet-stream Size: 1839 bytes Desc: not available URL: -------------- next part -------------- HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 05:29:24 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 23:29:24 -0400 Subject: [C++-sig] RuntimeError: unidentifiable C++ exception References: <1f527df80608300109q5f9df417sf8d1a23023a0a3b7@mail.gmail.com> Message-ID: <873baxpxt7.fsf@pereiro.luannocracy.com> "Qun Cao" writes: > Hi Everyone, > > I created a simple class wrapper like this > > BOOST_PYTHON_MODULE(PythonTest) { > class_("pMyClass", init()); > } > > When I try to initialize pMyClass in python, I got this error: > > Traceback (most recent call last): > File "", line 1, in ? > RuntimeError: unidentifiable C++ exception > > MyClass is part of a third party GameEngine, I can successfully use it in C++. > Can anyone suggest what might went wrong here? Either: a. Your C++ class threw some exception for which there's no pre-registered Boost.Python exception translator, or b. You're running on windows and your C++ code crashed. To find out if this is the case, add the following code to your module source file: # ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4297) # pragma warning(disable:4535) extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*) { throw; } extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*) = _set_se_translator(straight_to_debugger); # pragma warning(pop) # endif That will cause crashes to look like crashes rather than exceptions. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 05:30:24 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 23:30:24 -0400 Subject: [C++-sig] [tutorial] Auto-Overloading example bug? References: <7465b6170608300429n564516bfi22c665cd6cbfca32@mail.gmail.com> <44F666B8.9080609@boost-consulting.com> <44F67B9F.5060802@boost-consulting.com> <7465b6170608311021y2f5bebecr90ab1766c5b84ad2@mail.gmail.com> <44F77280.80103@boost-consulting.com> Message-ID: <87wt89oj73.fsf@pereiro.luannocracy.com> Joel de Guzman writes: > Roman Yakovenko wrote: >> On 8/31/06, Joel de Guzman wrote: >>> Ok, disregard that. I did check it out and the error is the def it >>> should be: >>> >>> .def("foo", (void(*)(bool, int, char))0, foo_overloads()); >>> >>> I fixed the docs and updated to CVS. >> >> Do you want to consider to fix "def"? >> >> .def("foo", foo_overloads() ); >> >> It is not clear why user should pass second argument. > > I don't think it can be fixed. The compiler does not have enough > information in there to know the exact signature needed. I may > be wrong though, so I'll investigate. If you know how to implement > this, I'm all ears. I don't think you're wrong. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 05:39:06 2006 From: dave at boost-consulting.com (David Abrahams) Date: Mon, 11 Sep 2006 23:39:06 -0400 Subject: [C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2) References: <44FE0AB2.8010006@pixar.com> <44FF3B6F.9030509@pixar.com> <45004B36.1020800@pixar.com> <45004EE9.7040604@pixar.com> Message-ID: <87r6yhoisl.fsf@pereiro.luannocracy.com> I don't have time to do a complete analysis right now, but maybe I can help understand these signatures: "Allen Bierbaum" writes: > // Next line shows problem where the object coming back > // out of C++ can't be compared. It is like it thinks it has > // a different type. >>>> g == core_g > Traceback (most recent call last): > File "", line 1, in ? > ArgumentError: Python argument types in > Group.__cmp__(Group, Group) > did not match C++ signature: > __cmp__(osg::RefPtr osg::NodeCore>, osg::Group> >, > osg::RefPtr osg::NodeCore>, osg::Group> >) It's not that the Python types are different (both are Group). It's much more likely that they have a different way of holding their internal C++ osg::Group object such that one can be converted to that RefPtr type and the other can't. What can be converted is up to the converters you've registered. > // This line shows the same problem with __hash__ >>>> hash(core_g) > Traceback (most recent call last): > File "", line 1, in ? > ArgumentError: Python argument types in > Group.__hash__(Group) > did not match C++ signature: > __hash__(osg::RefPtr osg::NodeCore>, osg::Group> >) > > // And here is the problem comparing to None >>>> g == None > Traceback (most recent call last): > File "", line 1, in ? > ArgumentError: Python argument types in > Group.__cmp__(Group, NoneType) > did not match C++ signature: > __cmp__(osg::RefPtr osg::NodeCore>, osg::Group> >, > osg::RefPtr osg::NodeCore>, osg::Group> >) >>>> This could be a case of the first (self) object not being convertible to the RefPtr. -- Dave Abrahams Boost Consulting www.boost-consulting.com From roman.yakovenko at gmail.com Tue Sep 12 07:03:00 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 12 Sep 2006 08:03:00 +0300 Subject: [C++-sig] [tutorial] Auto-Overloading example bug? In-Reply-To: <87wt89oj73.fsf@pereiro.luannocracy.com> References: <7465b6170608300429n564516bfi22c665cd6cbfca32@mail.gmail.com> <44F666B8.9080609@boost-consulting.com> <44F67B9F.5060802@boost-consulting.com> <7465b6170608311021y2f5bebecr90ab1766c5b84ad2@mail.gmail.com> <44F77280.80103@boost-consulting.com> <87wt89oj73.fsf@pereiro.luannocracy.com> Message-ID: <7465b6170609112203h69b9484bw63bca80b48a783bb@mail.gmail.com> On 9/12/06, David Abrahams wrote: > Joel de Guzman writes: > > > Roman Yakovenko wrote: > >> On 8/31/06, Joel de Guzman wrote: > >>> Ok, disregard that. I did check it out and the error is the def it > >>> should be: > >>> > >>> .def("foo", (void(*)(bool, int, char))0, foo_overloads()); > >>> > >>> I fixed the docs and updated to CVS. > >> > >> Do you want to consider to fix "def"? > >> > >> .def("foo", foo_overloads() ); > >> > >> It is not clear why user should pass second argument. > > > > I don't think it can be fixed. The compiler does not have enough > > information in there to know the exact signature needed. I may > > be wrong though, so I'll investigate. If you know how to implement > > this, I'm all ears. > > I don't think you're wrong. Actually my idea was simple: foo_overloads class derives from boost::python::detail::overloads_base class. I think you can use this fact and to remove the need to pass function signature to the "def". -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From anderslanglands at gmail.com Tue Sep 12 10:50:47 2006 From: anderslanglands at gmail.com (anders langlands) Date: Tue, 12 Sep 2006 09:50:47 +0100 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <45060B2B.1000703@sympatico.ca> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> <4505637E.5000706@sympatico.ca> <57ffdb9c0609110717u4c7650e1m9932a033742f05d@mail.gmail.com> <45060B2B.1000703@sympatico.ca> Message-ID: <57ffdb9c0609120150m3fc961fbg6c78df9c63370087@mail.gmail.com> Sorry, I assumed it was clear since I know exactly what I mean! All the derived types do indeed define many additional methods that I want to use. By type() constructor, do you mean doing: b = getDerivedObjectAsBasePointer # This would fail as doSomeDerivedFunction is only defined for Derived, but python thinks b is a Base* # b.doSomeDerivedFunction() d = Derived( b ) d.doSomeDerivedFunction() This is basically what I want to do, but I want that to be hidden from the user. I want to do the type-checking and construction automatically. So I'd wrap getDerivedObjectAsBasePointer with a pure python function, getDerivedObject, defined in my module's __init__.py. I'd like to generate the code for this python function automatically from C++ at module initialization time, since I know the typenames of all my classes then, and each of them has to register itself anyway, so *if* I can get access to the globals, I can define the dict which defines the functions for doing run-time type() constructors on my base class pointers. Does this make it any clearer? This doesn't gain me anything over doing the type() constructors manually in python, but I'd like to save users this extra leg work. It'll make the resulting scripts easier to read as well. A On 9/12/06, Stefan Seefeld wrote: > > anders langlands wrote: > > Thanks stefan, that does indeed look pretty simple! > > > > However, is there any way I can do this with having my own interpreter? > > > > The problem I am trying to solve is this: > > > > I have a large class library I want to bind to python. Everything in the > > library (Derived) is derived ultimately from a single class, Base. Now I > > have functions to serialize and deserialize objects to disk. The > > deserialize > > function returns a Derived object as a Base*. When this Base* is passed > > back > > to python, python doesn't know that it's actually a Derived object, and > it > > would be nice if it did. I basically want to be able to automatically > cast > > the Base object to whichever flavour of Derived object it actually is in > > python. > > > > No all my objects support the functions typeId() and typename() to get > > information about what they are. So the solution I've come up with is > this. > > I just store a big dict or list in the globals which maps typeId's to > > functions. These functions do the conversion of the base type to the > > derived > > type and the whole thing looks something like this: > > I'm not sure I understand the purpose of your downcasting. Those derived > python classes don't offer any additional attributes over what 'Base' > already has, or do they ? > If not, what advantage do you get from having the type names differ, > instead of using your own type system (provided by 'typeId()' and > 'typename()' ? > > If you really want to generate python types for the many C++ classes, > and you can do the conversion at runtime (as opposed to compile-time), > you may consider doing all of this from within a python module, by means > of the 'type()' constructor. > > But again, I don't yet understand what you are aiming at, since that > won't give you anything you couldn't get by directly querying an object's > typeId(). > > Thanks, > Stefan > > -- > > ...ich hab' noch einen Koffer in Berlin... > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Gottfried.Ganssauge at haufe.de Tue Sep 12 10:54:42 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Tue, 12 Sep 2006 10:54:42 +0200 Subject: [C++-sig] New Patch for opaque_pointer_converter In-Reply-To: <87zmd5q3nx.fsf@pereiro.luannocracy.com> Message-ID: <51F4AD92DB06E9488BBC39B7B492409E027C2016@vg20ex1.grp.haufemg.com> > -----Original Message----- > From: c++-sig-bounces at python.org > [mailto:c++-sig-bounces at python.org] On Behalf Of David Abrahams > Sent: Tuesday, September 12, 2006 3:23 AM > To: c++-sig at python.org > Subject: Re: [C++-sig] New Patch for opaque_pointer_converter > > Gottfried Gan?auge writes: > > > Please find attached a completely new patch against the > current CVS Head. > > This incorporates my patch from earlier today into the CVS Head. > > Further I implemented cross module support in so far as the > converter > > registers itself only if not another module already has > registered the > > same converter before. > > The opaque test case has been update to check for the segmentation > > fault mentioned in my previous post. > > A test case for the cross module support is included > (crossmod_opaque). > > > > I also updated the documentation for opaque. > > > > I tested my patch with > > - GCC-4.1 running on GNU/Linux 2.6.16.21-0.13-default x86_64 > > - Visual-C++-6.5 running on Windows XP > > - Visual-C++-7.1 running on Windows XP > > > > Feel free to check it in. If it's just a bug fix, you can > merge it into the release branch as well. I would ... if I could :-) I'm not an "authorized" boost developer (I'm _not_ planning to become one) so sourceforge won't let me in. Cheers, Gottfried > > -- > Dave Abrahams > Boost Consulting > www.boost-consulting.com > > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From Gottfried.Ganssauge at haufe.de Tue Sep 12 12:49:24 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Tue, 12 Sep 2006 12:49:24 +0200 Subject: [C++-sig] Py++ - problem with split_module and return_opaque_pointer-policy Message-ID: <51F4AD92DB06E9488BBC39B7B492409E029FDC9A@vg20ex1.grp.haufemg.com> The return_value_policy requires an additional macro call (BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID) in the declaration section of a module. This can be added e.g. using module_builder_t.add_declaration_code(), and it works as long as you're generating the code using write_module(). In the moment you're using "split_module" to split your output, this scheme breaks, because BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID is required in every translation unit using the opaque pointer type whose type_id is defined with that macro. Instead it is only generated into the main module. An example: test.hpp: ========= typedef struct opaque_ *opaque_pointer; opaque_pointer get_opaque(); test.py: ======== import os from pyplusplus import module_builder from pyplusplus.decl_wrappers import \ return_value_policy, \ return_opaque_pointer mb = module_builder.module_builder_t( ["test.hpp"] ) mb.add_declaration_code ("BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)") mb.free_function (name = "get_opaque").call_policies = \ return_value_policy (return_opaque_pointer) mb.build_code_creator( module_name='test_opaque' ) mb.split_module( '.' ) When compiled with g++ -c -I/usr/include/python2.4 test_opaque*cpp this produces the following sermon: boost/python/type_id.hpp: In function `boost::python::type_info boost::python::type_id() [with T = opaque_]': boost/python/lvalue_from_pytype.hpp:23: instantiated from `boost::python::type_info boost::python::detail::extractor_type_id(T&(*)(U)) [with T = opaque_, U = boost::python::opaque_pointer_converter::instance&]' boost/python/lvalue_from_pytype.hpp:88: instantiated from `boost::python::lvalue_from_pytype::lvalue_from_pytype() [with Extractor = boost::python::opaque_pointer_converter, const PyTypeObject*python_type = ((const PyTypeObject*)(&boost::python::opaque_pointer_converter::type_ object))]' boost/python/opaque_pointer_converter.hpp:116: instantiated from `void boost::python::opaque_pointer_converter::register_self() [with Pointer = opaque_*]' boost/python/opaque_pointer_converter.hpp:70: instantiated from `boost::python::opaque_pointer_converter::opaque_pointer_conver ter(const char*) [with Pointer = opaque_*]' boost/python/return_opaque_pointer.hpp:25: instantiated from `PyObject* boost::python::detail::opaque_conversion_holder::operator()(Poi nter) const [with Pointer = opaque_*]' boost/python/detail/invoke.hpp:75: instantiated from `PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_< false, false>, const RC&, F&) [with RC = boost::python::detail::opaque_conversion_holder, F = opaque_*(*)()]' boost/python/detail/caller.hpp:199: instantiated from `PyObject* boost::python::detail::caller_arity<0u>::impl::operator()(PyObject*, PyObject*) [with F = opaque_*(*)(), Policies = boost::python::return_value_policy, Sig = boost::mpl::vector1]' boost/python/object/py_function.hpp:38: instantiated from `PyObject* boost::python::objects::caller_py_function_impl::operator()(PyOb ject*, PyObject*) [with Caller = boost::python::detail::caller, boost::mpl::vector1 >]' test_opaque_free_functions.pypp.cpp:21: instantiated from here boost/python/type_id.hpp:71: error: invalid use of undefined type `struct opaque_' test.hpp:1: error: forward declaration of `struct opaque_' Cheers, Gottfried From roman.yakovenko at gmail.com Tue Sep 12 13:14:35 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 12 Sep 2006 14:14:35 +0300 Subject: [C++-sig] Py++ - problem with split_module and return_opaque_pointer-policy In-Reply-To: <51F4AD92DB06E9488BBC39B7B492409E029FDC9A@vg20ex1.grp.haufemg.com> References: <51F4AD92DB06E9488BBC39B7B492409E029FDC9A@vg20ex1.grp.haufemg.com> Message-ID: <7465b6170609120414r3935fd99mf0e957ad722f9542@mail.gmail.com> On 9/12/06, Ganssauge, Gottfried wrote: > The return_value_policy requires > an additional macro call (BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID) > in the declaration section of a module. > This can be added e.g. using module_builder_t.add_declaration_code(), > and it works as long as you're generating the code using write_module(). > > In the moment you're using "split_module" to split your output, this > scheme breaks, > because BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID is required in every > translation > unit using the opaque pointer type whose type_id is defined with that > macro. > Instead it is only generated into the main module. > Does "every translation unit" means "in every cpp file" ? If not the quick work-around I can propose is to put this macro in some header file and to include it. The solution to your problem requires small refactoring in Py++. I will do that before next release, but it will take some time. The solution will be to add "add_declaration_code" to free function: mb = module_builder.module_builder_t( ["test.hpp"] ) get_opaque = mb.free_function (name = "get_opaque") get_opaque.add_declaration_code("BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)") get_opaque.call_policies = return_value_policy (return_opaque_pointer) What do you think? -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From Gottfried.Ganssauge at haufe.de Tue Sep 12 13:37:07 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Tue, 12 Sep 2006 13:37:07 +0200 Subject: [C++-sig] Py++ - problem with split_module andreturn_opaque_pointer-policy In-Reply-To: <7465b6170609120414r3935fd99mf0e957ad722f9542@mail.gmail.com> Message-ID: <51F4AD92DB06E9488BBC39B7B492409E029FDCA8@vg20ex1.grp.haufemg.com> > -----Original Message----- > From: c++-sig-bounces at python.org > [mailto:c++-sig-bounces at python.org] On Behalf Of Roman Yakovenko > Sent: Tuesday, September 12, 2006 1:15 PM > To: Development of Python/C++ integration > Subject: Re: [C++-sig] Py++ - problem with split_module > andreturn_opaque_pointer-policy > > On 9/12/06, Ganssauge, Gottfried wrote: > > The return_value_policy requires an > additional > > macro call (BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID) > > in the declaration section of a module. > > This can be added e.g. using > module_builder_t.add_declaration_code(), > > and it works as long as you're generating the code using > write_module(). > > > > In the moment you're using "split_module" to split your > output, this > > scheme breaks, because BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID is > > required in every translation unit using the opaque pointer > type whose > > type_id is defined with that macro. > > Instead it is only generated into the main module. > > > > Does "every translation unit" means "in every cpp file" ? Yes. > If not the quick work-around I can propose is to put this macro in > some header file > and to include it. :-( > > The solution to your problem requires small refactoring in Py++. I > will do that before next > release, but it will take some time. > The solution will be to add "add_declaration_code" to free function: > > mb = module_builder.module_builder_t( ["test.hpp"] ) > > get_opaque = mb.free_function (name = "get_opaque") > > get_opaque.add_declaration_code("BOOST_PYTHON_OPAQUE_SPECIALIZ > ED_TYPE_ID(opaque_)") > get_opaque.call_policies = return_value_policy (return_opaque_pointer) > > What do you think? Sounds not too bad, but how about member functions returning opaque pointers? What do you think about a code generator more "knowledgeable" about return_value_policy? One that could see "hey, I'm being ordered to return_opaque_pointer" and then would call that macro wherever neccessary? In the code generator it could go like: if calling_policy is return_value_policy(return_opaque_pointer): opaque_base = remove_pointer (current_decl.return_value.type) add_declaration_code ('BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % opaque_base) > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > Cheers, Gottfried From roman.yakovenko at gmail.com Tue Sep 12 13:43:59 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 12 Sep 2006 14:43:59 +0300 Subject: [C++-sig] Py++ - problem with split_module andreturn_opaque_pointer-policy In-Reply-To: <51F4AD92DB06E9488BBC39B7B492409E029FDCA8@vg20ex1.grp.haufemg.com> References: <7465b6170609120414r3935fd99mf0e957ad722f9542@mail.gmail.com> <51F4AD92DB06E9488BBC39B7B492409E029FDCA8@vg20ex1.grp.haufemg.com> Message-ID: <7465b6170609120443s7ef51998p425e7b70ada260f9@mail.gmail.com> On 9/12/06, Ganssauge, Gottfried wrote: > What do you think about a code generator more "knowledgeable" about > return_value_policy? > One that could see "hey, I'm being ordered to return_opaque_pointer" and > then would call that macro wherever neccessary? > In the code generator it could go like: > if calling_policy is return_value_policy(return_opaque_pointer): > opaque_base = remove_pointer (current_decl.return_value.type) > add_declaration_code ('BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' > % opaque_base) This is even better solution. I will implement it and will let you know. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From dave at boost-consulting.com Tue Sep 12 14:17:59 2006 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 12 Sep 2006 08:17:59 -0400 Subject: [C++-sig] [tutorial] Auto-Overloading example bug? References: <7465b6170608300429n564516bfi22c665cd6cbfca32@mail.gmail.com> <44F666B8.9080609@boost-consulting.com> <44F67B9F.5060802@boost-consulting.com> <7465b6170608311021y2f5bebecr90ab1766c5b84ad2@mail.gmail.com> <44F77280.80103@boost-consulting.com> <87wt89oj73.fsf@pereiro.luannocracy.com> <7465b6170609112203h69b9484bw63bca80b48a783bb@mail.gmail.com> Message-ID: <87odtlcm88.fsf@pereiro.luannocracy.com> "Roman Yakovenko" writes: > Actually my idea was simple: foo_overloads class derives from > boost::python::detail::overloads_base class. I think you can use > this fact and to remove the need to pass function signature to the > "def". How? We need to be able to access the argument types at compile-time. Anyway, if you think it can be done, please show us with actual working code, because I'm pretty sure it's impossible. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 14:20:12 2006 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 12 Sep 2006 08:20:12 -0400 Subject: [C++-sig] New Patch for opaque_pointer_converter References: <87zmd5q3nx.fsf@pereiro.luannocracy.com> <51F4AD92DB06E9488BBC39B7B492409E027C2016@vg20ex1.grp.haufemg.com> Message-ID: <87irjtcm4j.fsf@pereiro.luannocracy.com> "Ganssauge, Gottfried" writes: >> -----Original Message----- >> From: c++-sig-bounces at python.org >> [mailto:c++-sig-bounces at python.org] On Behalf Of David Abrahams >> Sent: Tuesday, September 12, 2006 3:23 AM >> To: c++-sig at python.org >> Subject: Re: [C++-sig] New Patch for opaque_pointer_converter >> >> Gottfried Gan?auge writes: >> >> > Please find attached a completely new patch against the >> current CVS Head. >> > This incorporates my patch from earlier today into the CVS Head. >> > Further I implemented cross module support in so far as the >> converter >> > registers itself only if not another module already has >> registered the >> > same converter before. >> > The opaque test case has been update to check for the segmentation >> > fault mentioned in my previous post. >> > A test case for the cross module support is included >> (crossmod_opaque). >> > >> > I also updated the documentation for opaque. >> > >> > I tested my patch with >> > - GCC-4.1 running on GNU/Linux 2.6.16.21-0.13-default x86_64 >> > - Visual-C++-6.5 running on Windows XP >> > - Visual-C++-7.1 running on Windows XP >> > >> >> Feel free to check it in. If it's just a bug fix, you can >> merge it into the release branch as well. > I would ... if I could :-) > I'm not an "authorized" boost developer (I'm _not_ planning to become one) so sourceforge won't let me in. Why not? Anyway, I'm under a bit of pressure and I don't have time to merge your patches right now. If you don't want CVS access yourself and you can't find anyone else to merge them, please stick them in the patches tracker at SF so they'll be there when I _do_ find the time. Thanks, -- Dave Abrahams Boost Consulting www.boost-consulting.com From seefeld at sympatico.ca Tue Sep 12 15:24:00 2006 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Tue, 12 Sep 2006 09:24:00 -0400 Subject: [C++-sig] PyCode_New and new.code() functions In-Reply-To: <57ffdb9c0609120150m3fc961fbg6c78df9c63370087@mail.gmail.com> References: <57ffdb9c0609110356w609c73d3ic969cc28bcfe5dde@mail.gmail.com> <45054B4B.1000303@sympatico.ca> <57ffdb9c0609110524w53fc9337ya212489ab859bda4@mail.gmail.com> <4505637E.5000706@sympatico.ca> <57ffdb9c0609110717u4c7650e1m9932a033742f05d@mail.gmail.com> <45060B2B.1000703@sympatico.ca> <57ffdb9c0609120150m3fc961fbg6c78df9c63370087@mail.gmail.com> Message-ID: <4506B4F0.3010907@sympatico.ca> anders langlands wrote: > Sorry, I assumed it was clear since I know exactly what I mean! > > All the derived types do indeed define many additional methods that I want > to use. While in python you can construct types at runtime (you don't even need the python parser for that !), in C++ you can't. All your C++ API reflection has to happen at compile-time. You may then rewrap the results however you want from inside a running python instance. > By type() constructor, do you mean doing: I mean something like ---- from base import Base Derived = type('Derived', (Base,), {}) ---- which lets you create a new type 'Derived' in a functional way. Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin... From judog at campus.ie Tue Sep 12 16:27:49 2006 From: judog at campus.ie (Gordon Blackshields) Date: Tue, 12 Sep 2006 22:27:49 +0800 Subject: [C++-sig] ImportError for boost.python tutorial Message-ID: <20060912142749.C02D7245E5@ws5-3.us4.outblaze.com> Hi everyone, I found this post made back in march in an attempt to get started with boost.python using mingw, after unsuccessfully trying the seemingly very simple example given in the tutorial ("hello.cpp"). After following the advice given in the link (creating the libpython24.a file and so on using pexports and dlltool and so on) but I'm still hitting a brick wall when trying to get the module imported in the interpreter. ("ImportError: dynamic module does not define init function (inithello)") I have the .dll and .pyd files made ok, but pexports shows that hello.pyd isn't exporting inithello as expected. Are there other underlying causes for this import error that i'm just not seeing? The original post that I found is below (the post was cunningly entitled "Problem") Thanks in advance, Gordon Hi, I am not sure this will solve your problem but just in case... I also had similar problems at the beginning. The problem was that the python library shipped with Python installation only works with Microsoft compatible link and I was using, as you do, mingw (gcc). In http://www.boost.org/libs/python/doc/building.html#mingw you will find a detail explanation of what happens and how to solve it. It's really simple. Hope this will help... It is really frustrating at the beginning but once it starts working... boost::python is wonderful! Best Regards, Pedro. > Hi, > I'm trying to build the basic boost.python tutorial that comes with the > distribution. I'm using bjam and mingw. It builds the module, but > upon import, it gives this error: > > ImportError: dynamic module does not define init function (inithello) > > I've found other threads with this problem as a topic, but no > solutions. Somebody has to have solved this.... > > Any ideas? > > Thanks, > -Justin > > OH yeah, I'm using Active Python (perhaps that's it?) -- Pedro -- _______________________________________________ For the largest FREE email in Ireland (25MB) and 20MB of online file storage space - Visit http://www.campus.ie From jack833 at 163.com Tue Sep 12 18:18:52 2006 From: jack833 at 163.com (jack833) Date: Tue, 12 Sep 2006 09:18:52 -0700 (PDT) Subject: [C++-sig] Help about warning C4541 in using VC7.1 Message-ID: <6269389.post@talk.nabble.com> Here is My code . but show out warnning C4541 in VC7.1 namespace Unitest { namespace UTester { class UTester { public: UTester(){} virtual ~UTester(){} std::string Foo(){return "FOO";} }; } } warnning show: E:\ProgramFiles\Microsoft Visual Studio.NET 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(43) : warning C4541: ?dynamic_cast?using option /GR- at a Polymorphism ?Unitest::UTester::UTester??May be result in unpredictable behavior. E:\ProgramFiles\Microsoft Visual Studio.NET 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(41) : while compile template class member function?boost::python::objects::dynamic_id_t boost::python::objects::polymorphic_id_generator::execute(void *)? with [ T=Unitest::UTester::UTester ] can any one help me? -- View this message in context: http://www.nabble.com/Help-about-warning-C4541-in-using-VC7.1-tf2259871.html#a6269389 Sent from the Python - c++-sig forum at Nabble.com. From amohr at pixar.com Tue Sep 12 18:36:06 2006 From: amohr at pixar.com (Alex Mohr) Date: Tue, 12 Sep 2006 09:36:06 -0700 Subject: [C++-sig] What if a Python override returns several values? In-Reply-To: <87k649q33b.fsf@pereiro.luannocracy.com> References: <44FDABA2.60809@pixar.com> <87k649q33b.fsf@pereiro.luannocracy.com> Message-ID: <4506E1F6.5080604@pixar.com> >>> But if I have another virtual member function "void g(int& a, int &b)" >>> which returns two integers, then I'd like the Python version to take no >>> arguments and return a tuple (a,b). But how does the wrapper look like >>> in this case? I would have expected something like: >>> >>> void g(int& a, int& b) >>> { >>> boost::python::tuple tup = this->get_override("g")(); >>> >>> a = ...extract an int from tup[0]... >>> b = ...extract an int from tup[1]... >>> } >>> >>> But when I run this code I get the following error at runtime: >>> >>> TypeError: No registered converter was able to extract a C++ reference >>> to type boost::python::tuple from this Python object of type tuple >> Not sure exactly what's going on here, but you might be able to find out >> by looking at override.hpp. Look at method_result -- that's what you're >> getting back from get_override. >> >> Off the top of my head, I think this would probably work for you: >> >> tuple tup = call(this->get_override("g").ptr()); > >> a = ...extract an int from tup[0] >> b = ...extract an int from tup[1] > > > I don't know why people always use ugly low-level interfaces when they > can use beautiful high-level ones: > > python::tuple tup = this->get_override("g")(); > a = extract(tup[0]); > . > . > . Isn't this what the original poster had, and claimed didn't work? I agree that this is what should be written. I was merely suggesting a workaround. What am I missing? > There's almost never a reason to use call<> anymore! I should > deprecate it. Please don't -- I use it in some low-level code. > I'm not trying to be critical, but this really concerns me. I see > this sort of thing all the time. If you could help me understand > why you were moved to suggest doing it the hard way, I would > appreciate it. Again, just because the original (which as far as I can see is the same as what you suggested) didn't work. I was just suggesting a workaround. I wouldn't suggest it as the "correct" solution. Alex From seefeld at sympatico.ca Tue Sep 12 18:50:13 2006 From: seefeld at sympatico.ca (Stefan Seefeld) Date: Tue, 12 Sep 2006 12:50:13 -0400 Subject: [C++-sig] Help about warning C4541 in using VC7.1 In-Reply-To: <6269389.post@talk.nabble.com> References: <6269389.post@talk.nabble.com> Message-ID: <4506E545.9040901@sympatico.ca> jack833 wrote: > Here is My code . but show out warnning C4541 in VC7.1 > namespace Unitest > { > namespace UTester > { > class UTester > { > public: > UTester(){} > virtual ~UTester(){} > std::string Foo(){return "FOO";} > }; > } > } This code doesn't appear to have anything to do with boost.python, and neither with the error message from VS for that matter. > warnning show: > E:\ProgramFiles\Microsoft Visual Studio.NET > 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(43) : warning > C4541: ?dynamic_cast?using option /GR- at a Polymorphism > ?Unitest::UTester::UTester??May be result in unpredictable behavior. > E:\ProgramFiles\Microsoft Visual Studio.NET > 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(41) : while > compile template class member function?boost::python::objects::dynamic_id_t > boost::python::objects::polymorphic_id_generator::execute(void *)? > with > [ > T=Unitest::UTester::UTester > ] > > can any one help me? Well, enable /GR (and /GX, while we are at it, since boost.python may throw exceptions, too) ! Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin... From Gottfried.Ganssauge at haufe.de Tue Sep 12 19:09:53 2006 From: Gottfried.Ganssauge at haufe.de (Ganssauge, Gottfried) Date: Tue, 12 Sep 2006 19:09:53 +0200 Subject: [C++-sig] New Patch for opaque_pointer_converter In-Reply-To: <87irjtcm4j.fsf@pereiro.luannocracy.com> Message-ID: <51F4AD92DB06E9488BBC39B7B492409E029FDD0D@vg20ex1.grp.haufemg.com> > > I'm not an "authorized" boost developer (I'm _not_ planning > to become one) so sourceforge won't let me in. > > Why not? Because I couldn't easyly find out, how :-) In earnest - I already got quite a few responsibilities and I don't take things like that easy. > > Anyway, I'm under a bit of pressure and I don't have time to > merge your patches right now. If you don't want CVS access > yourself and you can't find anyone else to merge them, please > stick them in the patches tracker at SF so they'll be there > when I _do_ find the time. OK. Just put it in under ID boost-Patches-1557285. > > Thanks, Cheers, Gottfried > > -- > Dave Abrahams > Boost Consulting > www.boost-consulting.com > > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > From dave at boost-consulting.com Tue Sep 12 19:36:34 2006 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 12 Sep 2006 13:36:34 -0400 Subject: [C++-sig] New Patch for opaque_pointer_converter References: <87irjtcm4j.fsf@pereiro.luannocracy.com> <51F4AD92DB06E9488BBC39B7B492409E029FDD0D@vg20ex1.grp.haufemg.com> Message-ID: "Ganssauge, Gottfried" writes: >> > I'm not an "authorized" boost developer (I'm _not_ planning >> to become one) so sourceforge won't let me in. >> >> Why not? > Because I couldn't easyly find out, how :-) You send your SourceForge userid to boost-owner at lists.boost.org and ask. Signing up at SourceForge is fairly trivial if you haven't done it. > In earnest - I already got quite a few responsibilities and I don't take > things like that easy. > >> >> Anyway, I'm under a bit of pressure and I don't have time to >> merge your patches right now. If you don't want CVS access >> yourself and you can't find anyone else to merge them, please >> stick them in the patches tracker at SF so they'll be there >> when I _do_ find the time. > OK. > Just put it in under ID boost-Patches-1557285. Thanks, I appreciate it. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Tue Sep 12 21:51:42 2006 From: dave at boost-consulting.com (David Abrahams) Date: Tue, 12 Sep 2006 15:51:42 -0400 Subject: [C++-sig] What if a Python override returns several values? References: <44FDABA2.60809@pixar.com> <87k649q33b.fsf@pereiro.luannocracy.com> <4506E1F6.5080604@pixar.com> Message-ID: Alex Mohr writes: >>>> But if I have another virtual member function "void g(int& a, int &b)" >>>> which returns two integers, then I'd like the Python version to take no >>>> arguments and return a tuple (a,b). But how does the wrapper look like >>>> in this case? I would have expected something like: >>>> >>>> void g(int& a, int& b) >>>> { >>>> boost::python::tuple tup = this->get_override("g")(); >>>> >>>> a = ...extract an int from tup[0]... >>>> b = ...extract an int from tup[1]... >>>> } >>>> >>>> But when I run this code I get the following error at runtime: >>>> >>>> TypeError: No registered converter was able to extract a C++ reference >>>> to type boost::python::tuple from this Python object of type tuple >>> Not sure exactly what's going on here, but you might be able to find out >>> by looking at override.hpp. Look at method_result -- that's what you're >>> getting back from get_override. >>> >>> Off the top of my head, I think this would probably work for you: >>> >>> tuple tup = call(this->get_override("g").ptr()); >> >>> a = ...extract an int from tup[0] >>> b = ...extract an int from tup[1] >> >> >> I don't know why people always use ugly low-level interfaces when they >> can use beautiful high-level ones: >> >> python::tuple tup = this->get_override("g")(); >> a = extract(tup[0]); >> . >> . >> . > > Isn't this what the original poster had, and claimed didn't work? Nope. > I agree that this is what should be written. I was merely > suggesting a workaround. What am I missing? boost::tuple != boost::python::tuple. >> There's almost never a reason to use call<> anymore! I should >> deprecate it. > > Please don't -- I use it in some low-level code. Do you actually need it? >> I'm not trying to be critical, but this really concerns me. I see >> this sort of thing all the time. If you could help me understand >> why you were moved to suggest doing it the hard way, I would >> appreciate it. > > Again, just because the original (which as far as I can see is the same > as what you suggested) didn't work. I was just suggesting a workaround. > I wouldn't suggest it as the "correct" solution. OK, thanks for the explanation. -- Dave Abrahams Boost Consulting www.boost-consulting.com From amohr at pixar.com Tue Sep 12 22:32:22 2006 From: amohr at pixar.com (Alex Mohr) Date: Tue, 12 Sep 2006 13:32:22 -0700 Subject: [C++-sig] What if a Python override returns several values? In-Reply-To: References: <44FDABA2.60809@pixar.com> <87k649q33b.fsf@pereiro.luannocracy.com> <4506E1F6.5080604@pixar.com> Message-ID: <45071956.2020104@pixar.com> David Abrahams wrote: >>>>> But if I have another virtual member function "void g(int& a, int &b)" >>>>> which returns two integers, then I'd like the Python version to take no >>>>> arguments and return a tuple (a,b). But how does the wrapper look like >>>>> in this case? I would have expected something like: >>>>> >>>>> void g(int& a, int& b) >>>>> { >>>>> boost::python::tuple tup = this->get_override("g")(); >>>>> >>>>> a = ...extract an int from tup[0]... >>>>> b = ...extract an int from tup[1]... >>>>> } >>>>> >>>>> But when I run this code I get the following error at runtime: >>>>> >>>>> TypeError: No registered converter was able to extract a C++ reference >>>>> to type boost::python::tuple from this Python object of type tuple >>>> Not sure exactly what's going on here, but you might be able to find out >>>> by looking at override.hpp. Look at method_result -- that's what you're >>>> getting back from get_override. >>>> >>>> Off the top of my head, I think this would probably work for you: >>>> >>>> tuple tup = call(this->get_override("g").ptr()); >>>> a = ...extract an int from tup[0] >>>> b = ...extract an int from tup[1] >>> >>> I don't know why people always use ugly low-level interfaces when they >>> can use beautiful high-level ones: >>> >>> python::tuple tup = this->get_override("g")(); >>> a = extract(tup[0]); >>> . >>> . >>> . >> Isn't this what the original poster had, and claimed didn't work? > > Nope. > >> I agree that this is what should be written. I was merely >> suggesting a workaround. What am I missing? > > boost::tuple != boost::python::tuple. > Clearly that's a true statement, but I don't see where boost::tuple is coming from. My eyes must be broken. I'll copy-paste the original code, quoted earlier in this message. void g(int& a, int& b) { boost::python::tuple tup = this->get_override("g")(); a = ...extract an int from tup[0]... b = ...extract an int from tup[1]... } Compare this with the code you posted: >> python::tuple tup = this->get_override("g")(); >> a = extract(tup[0]); The poster says the error message he gets is: TypeError: No registered converter was able to extract a C++ reference to type boost::python::tuple from this Python object of type tuple Where is boost::tuple coming into play? I didn't see that at all anywhere in the thread. In my reply to the poster, I removed the boost::python:: prefix from my code, so I mentioned "tuple" directly. Perhaps that's what was causing confusion? I meant boost::python::tuple. Regardless, unless I'm reading it wrong (please show me how!) I believe that the code you posted is identical to the original posted code. >>> There's almost never a reason to use call<> anymore! I should >>> deprecate it. >> Please don't -- I use it in some low-level code. > > Do you actually need it? I think so. It's in some template code, where the return type is a template parameter, and is allowed to be void, and IIRC, the problem was that saying "return extract(callable(...));" doesn't work. Whereas saying "return call(callable.ptr(), ...));" does. I guess I'd prefer to keep call<> around so I don't have to specialize the whole thing for the case of void. I can try reworking it to avoid using call later in the week and get back to you. Alex From roman.yakovenko at gmail.com Tue Sep 12 22:55:54 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Tue, 12 Sep 2006 23:55:54 +0300 Subject: [C++-sig] custom smart pointers In-Reply-To: <878xkppxyq.fsf@pereiro.luannocracy.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <878xkppxyq.fsf@pereiro.luannocracy.com> Message-ID: <7465b6170609121355q42dc2dc7m526e6eaf5c3344ff@mail.gmail.com> On 9/12/06, David Abrahams wrote: > I made your example work. I had to add an operator* to your smart > pointer, although I think that uncovers a bug in Boost.Python: we > should be using get_pointer where it needed the operator*, instead. > > I don't know if this meets your needs or not, but the result is > enclosed. Thank you for your time and help. Unfortunately it did not help :-(. I reworked the example, base on your comments. I had to add next conversion: bp::implicitly_convertible< smart_ptr_t< base_wrapper_t >, smart_ptr_t< base_i > >(); There are still 2 problems: I am not able to call functions that take reference and const reference to smart_ptr_t< base > instance. int ref_get_value( smart_ptr_t& a ){ return a->get_value(); } I am unable to call this function, I've got ArgumentError exception int const_ref_get_value( const smart_ptr_t& a ){ return a->get_value(); } I am unable to call this function, I've got "segmentation fault" on Linux. I attached test.py file that checks all the functions. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ -------------- next part -------------- A non-text attachment was scrubbed... Name: cspc.cpp Type: text/x-c++src Size: 5276 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: test.py Type: text/x-python Size: 1298 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Jamroot Type: application/octet-stream Size: 380 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: boost-build.jam Type: application/octet-stream Size: 283 bytes Desc: not available URL: From roman.yakovenko at gmail.com Wed Sep 13 13:22:46 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Wed, 13 Sep 2006 14:22:46 +0300 Subject: [C++-sig] Py++ generated code ( was custom smart pointers ) Message-ID: <7465b6170609130422i4f54ac36se9aa220e56a767da@mail.gmail.com> On 9/12/06, David Abrahams wrote: > A minimal example would have no "documentation" stringsno use of > named arguments (bp::arg(...)) and no use of things that you get by > default anyway, like default_call_policies. It would not contain > extraneous implicit conversions from int. This is a problem with many > code generators: they create an unreadable mess for anyone who wants > to understand the result. Part of the reason many people despise the > MFC Wizards. I suggest you fix Py++ so it doesn't add vacuous > "documentation" and other needless cruft. 1. Documentation was my fault. By default Py++ does not generate it. 2. default call policies is not generated anymore 3. implicit conversion - well, Py++ tries to generate as "complete code" as possible. This is done for few reasons: * educational reasons, new users to Boost.Python can learn a lot from Py++ generated code. Py++ even has gui: http://language-binding.net/pyplusplus/tutorials/pyplusplus_demo.png * to minimize size of driving script * to minimize Py++ learning curve This case is a little bit special, because a "bug" in C++. Constructors in C++ should be explicit by default. The bottom line is that I turned off generation of "implicit conversion" for constructors. In general, Py++ generates very readable code. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From dave at boost-consulting.com Wed Sep 13 13:45:01 2006 From: dave at boost-consulting.com (David Abrahams) Date: Wed, 13 Sep 2006 07:45:01 -0400 Subject: [C++-sig] ImportError for boost.python tutorial References: <20060912142749.C02D7245E5@ws5-3.us4.outblaze.com> Message-ID: <87ejugvvlu.fsf@pereiro.luannocracy.com> "Gordon Blackshields" writes: > Hi everyone, I found this post made back in march in an attempt to > get started with boost.python using mingw, after unsuccessfully > trying the seemingly very simple example given in the tutorial > ("hello.cpp"). > > After following the advice given in the link (creating the > libpython24.a file and so on using pexports and dlltool and so on) > but I'm still hitting a brick wall when trying to get the module > imported in the interpreter. ("ImportError: dynamic module does not > define init function (inithello)") Does the module source contain BOOST_PYTHON_MODULE(hello) ?? When you preprocess that file, you should see the necessary decorations on the declaration to make the symbol exported. If you're using Boost.Build, it should supply the right compiler command-line arguments to build a shared object. If you're not using Boost.Build, all bets are off. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Wed Sep 13 13:53:45 2006 From: dave at boost-consulting.com (David Abrahams) Date: Wed, 13 Sep 2006 07:53:45 -0400 Subject: [C++-sig] What if a Python override returns several values? References: <44FDABA2.60809@pixar.com> <87k649q33b.fsf@pereiro.luannocracy.com> <4506E1F6.5080604@pixar.com> <45071956.2020104@pixar.com> Message-ID: <878xkovv7a.fsf@pereiro.luannocracy.com> Alex Mohr writes: > Clearly that's a true statement, but I don't see where boost::tuple is > coming from. My eyes must be broken. I'll copy-paste the original > code, quoted earlier in this message. > > void g(int& a, int& b) { > boost::python::tuple tup = this->get_override("g")(); > a = ...extract an int from tup[0]... > b = ...extract an int from tup[1]... > } > > Compare this with the code you posted: > > >> python::tuple tup = this->get_override("g")(); > >> a = extract(tup[0]); > > The poster says the error message he gets is: > > TypeError: No registered converter was able to extract a C++ reference > to type boost::python::tuple from this Python object of type tuple > > Where is boost::tuple coming into play? Nowhere; I think it's my eyes that are broken, sorry! > I didn't see that at all > anywhere in the thread. In my reply to the poster, I removed the > boost::python:: prefix from my code, so I mentioned "tuple" directly. > Perhaps that's what was causing confusion? I meant boost::python::tuple. > > Regardless, unless I'm reading it wrong (please show me how!) I believe > that the code you posted is identical to the original posted code. Okay. Does it work if you don't use copy-initialization? boost::python::tuple tup(this->get_override("g")()); ? Does this work? boost::python::object t = this->get_override("g")(); boost::python::tuple tup(t); what about: boost::python::tuple tup = this->get_override("g")().as(); ?? >>>> There's almost never a reason to use call<> anymore! I should >>>> deprecate it. >>> Please don't -- I use it in some low-level code. >> >> Do you actually need it? > > I think so. It's in some template code, where the return type is a > template parameter, and is allowed to be void, and IIRC, the problem was > that saying "return extract(callable(...));" doesn't work. > Whereas saying "return call(callable.ptr(), ...));" does. I guess > I'd prefer to keep call<> around so I don't have to specialize the whole > thing for the case of void. > > I can try reworking it to avoid using call later in the week and get > back to you. Don't bother; I understand your problem. You need a facility something more like get_override and method_result, which the library doesn't supply for your case. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Wed Sep 13 14:03:16 2006 From: dave at boost-consulting.com (David Abrahams) Date: Wed, 13 Sep 2006 08:03:16 -0400 Subject: [C++-sig] Py++ generated code ( was custom smart pointers ) References: <7465b6170609130422i4f54ac36se9aa220e56a767da@mail.gmail.com> Message-ID: <87zmd4ug6z.fsf@pereiro.luannocracy.com> "Roman Yakovenko" writes: > On 9/12/06, David Abrahams wrote: > 3. implicit conversion - well, Py++ tries to generate as "complete > code" as possible. I'm not criticizing that part of what Py++ does; it's probably the right thing, but it shouldn't show up in a minimal example for tech support purposes (unless it's relevant, of course) > In general, Py++ generates very readable code. It's not bad; it would probably help if you did something to control the length of generated lines. -- Dave Abrahams Boost Consulting www.boost-consulting.com From dave at boost-consulting.com Wed Sep 13 14:24:45 2006 From: dave at boost-consulting.com (David Abrahams) Date: Wed, 13 Sep 2006 08:24:45 -0400 Subject: [C++-sig] custom smart pointers References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <878xkppxyq.fsf@pereiro.luannocracy.com> <7465b6170609121355q42dc2dc7m526e6eaf5c3344ff@mail.gmail.com> Message-ID: <87wt88uf76.fsf@pereiro.luannocracy.com> "Roman Yakovenko" writes: > On 9/12/06, David Abrahams wrote: >> I made your example work. I had to add an operator* to your smart >> pointer, although I think that uncovers a bug in Boost.Python: we >> should be using get_pointer where it needed the operator*, instead. >> >> I don't know if this meets your needs or not, but the result is >> enclosed. > > Thank you for your time and help. > > Unfortunately it did not help :-(. > I reworked the example, base on your comments. > > I had to add next conversion: > bp::implicitly_convertible< smart_ptr_t< base_wrapper_t >, > smart_ptr_t< base_i > >(); > > There are still 2 problems: I am not able to call functions that take > reference and const reference to smart_ptr_t< base > instance. FWIW, reference and const reference are totally separate cases. const reference is essentially the same as pass-by-value; it only requires an rvalue conversion. Mutable references require an lvalue conversion. > int ref_get_value( smart_ptr_t& a ){ > return a->get_value(); > } > > I am unable to call this function, I've got ArgumentError exception Naturally; there is no instance of smart_ptr_t anywhere in the Python object for the reference to bind to. The rules are the same as in C++: int f(smart_ptr_t& x) { return 0; } smart_ptr_t y; int z = f(y); // fails to compile > int const_ref_get_value( const smart_ptr_t& a ){ > return a->get_value(); > } > > I am unable to call this function, I've got "segmentation fault" on Linux. Where does the segmentation fault occur? Is 'a' a valid pointer within const_ref_get_value? > I attached test.py file that checks all the functions. Try building a minimal example that does nothing more than to reproduce your segmentation fault. Then we'll see if the problem is in Boost.Python or in your code. -- Dave Abrahams Boost Consulting www.boost-consulting.com From jack833 at 163.com Wed Sep 13 14:44:46 2006 From: jack833 at 163.com (jack833) Date: Wed, 13 Sep 2006 05:44:46 -0700 (PDT) Subject: [C++-sig] Help about warning C4541 in using VC7.1 In-Reply-To: <4506E545.9040901@sympatico.ca> References: <6269389.post@talk.nabble.com> <4506E545.9040901@sympatico.ca> Message-ID: <6284711.post@talk.nabble.com> Oh,I see,thank you for your help! Stefan Seefeld wrote: > > jack833 wrote: >> Here is My code . but show out warnning C4541 in VC7.1 >> namespace Unitest >> { >> namespace UTester >> { >> class UTester >> { >> public: >> UTester(){} >> virtual ~UTester(){} >> std::string Foo(){return "FOO";} >> }; >> } >> } > > This code doesn't appear to have anything to do with boost.python, > and neither with the error message from VS for that matter. > >> warnning show: >> E:\ProgramFiles\Microsoft Visual Studio.NET >> 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(43) : warning >> C4541: ?dynamic_cast?using option /GR- at a Polymorphism >> ?Unitest::UTester::UTester??May be result in unpredictable behavior. >> E:\ProgramFiles\Microsoft Visual Studio.NET >> 2003\Vc7\Boost\include\boost\python\object\inheritance.hpp(41) : while >> compile template class member >> function?boost::python::objects::dynamic_id_t >> boost::python::objects::polymorphic_id_generator::execute(void *)? >> with >> [ >> T=Unitest::UTester::UTester >> ] >> >> can any one help me? > > Well, enable /GR (and /GX, while we are at it, since boost.python may > throw > exceptions, too) ! > > Regards, > Stefan > > -- > > ...ich hab' noch einen Koffer in Berlin... > _______________________________________________ > C++-sig mailing list > C++-sig at python.org > http://mail.python.org/mailman/listinfo/c++-sig > > -- View this message in context: http://www.nabble.com/Help-about-warning-C4541-in-using-VC7.1-tf2259871.html#a6284711 Sent from the Python - c++-sig forum at Nabble.com. From eduardo.picado at gmail.com Wed Sep 13 18:56:26 2006 From: eduardo.picado at gmail.com (Eduardo Picado) Date: Wed, 13 Sep 2006 18:56:26 +0200 Subject: [C++-sig] Exception 'No to_python (by-value) converter found - 'garbage collection' Message-ID: <6c75ff8f0609130956s6b0e7c9m9fdb8d44840fd26b@mail.gmail.com> Hi, Im writing the following kind of python code using a C++ wrapped library: system = TASRSystem.getASRSystem() system.setParameter(TASRSystem.Option.asrServersListenPort, 32000) try: system.initialize(1, 3000) except Exception, e: sys.stderr.write("[E] : " + e.__class__.__name__ + str(e) ) print "ok" Running it I get: ok Exception exceptions.TypeError: 'No to_python (by-value) converter found for C++ type: class TASRSystem' in 'garbage collection' ignored Fatal Python error: unexpected exception during garbage collection The declaration of TASRSystem is like: BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(TASRSystem_initialize_overloads_0_2, initialize, 0, 2) class_< TASRSystem, boost::noncopyable >("TASRSystem", no_init) .def("getASRSystem", &TASRSystem::getASRSystem, return_value_policy()) .def("initialize", &TASRSystem::initialize, TASRSystem_initialize_overloads_0_2()) .staticmethod("getASRSystem") - TASRSystem.getASRSystem() is an static method, that creates and returns an instance of an ASRSystem. Seems ok. I've tried to use with_custodian_and_ward_postcall <1, 0>, to ensure that the lifetime of the created instance is as long as that of the Python object, but it didn't worked - gives "argument index out of range". - setParameter() seems good, as I can check with a .getParameter() call. - system.initialize() It doesn't return anything, I think it just tries to find/connect to remote ressources based on the parameters. It seems to work, the "ok" is printed but after it gives the "No to_python (by-value) converter found"... associated with the Python garbage collection... Some ideas? Thanks very much, Eduardo -- Eduardo PICADO MSN eduardo.picado at gmail.com portable +33 6 32 47 10 10 (NEW) fix +33 1 45 03 52 54 |????| From roman.yakovenko at gmail.com Wed Sep 13 21:10:31 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Wed, 13 Sep 2006 22:10:31 +0300 Subject: [C++-sig] custom smart pointers In-Reply-To: <87wt88uf76.fsf@pereiro.luannocracy.com> References: <7465b6170608291048y6e2010d4ofa84fbd5760da4d3@mail.gmail.com> <7465b6170608311358s1c02c6c9hc26222fae8cfdef6@mail.gmail.com> <878xkppxyq.fsf@pereiro.luannocracy.com> <7465b6170609121355q42dc2dc7m526e6eaf5c3344ff@mail.gmail.com> <87wt88uf76.fsf@pereiro.luannocracy.com> Message-ID: <7465b6170609131210h30285ef8pd4c8b7e624ff82f3@mail.gmail.com> On 9/13/06, David Abrahams wrote: > FWIW, reference and const reference are totally separate cases. const > reference is essentially the same as pass-by-value; it only requires > an rvalue conversion. Mutable references require an lvalue conversion. > > > int ref_get_value( smart_ptr_t& a ){ > > return a->get_value(); > > } > > > > I am unable to call this function, I've got ArgumentError exception > > Naturally; there is no instance of smart_ptr_t anywhere in the > Python object for the reference to bind to. The rules are the same > as in C++: > > int f(smart_ptr_t& x) { return 0; } > smart_ptr_t y; > int z = f(y); // fails to compile Thank you for explanation. > > int const_ref_get_value( const smart_ptr_t& a ){ > > return a->get_value(); > > } > > > > I am unable to call this function, I've got "segmentation fault" on Linux. > > Where does the segmentation fault occur? Is 'a' a valid pointer > within const_ref_get_value? > > > Try building a minimal example that does nothing more than to > reproduce your segmentation fault. Then we'll see if the problem is > in Boost.Python or in your code. I built one and I don't like what I see. Let me explain. smart_ptr_t{...}; struct derived_t{ virtual int get_value(){ return 11;} }; int val_get_value( smart_ptr_t a ){ return a->get_value(); } int const_ref_get_value( const smart_ptr_t& a ){ if( a.get() ) return a->get_value(); else return -1; } namespace boost{ namespace python{ get_pointer definition pointee definition } } Registration is pretty simple: bp::class_< derived_t, smart_ptr_t >( "derived_t" ) .def( "get_value", &::derived_t::get_value ); bp::def( "const_ref_get_value", &::const_ref_get_value ); bp::def( "val_get_value", &::val_get_value ); Python test code also simple: inst = cspc_ext.derived_t() cspc_ext.val_get_value(inst) cspc_ext.const_ref_get_value(inst) # <= in this line I get segmentation fault. Now the mistery I saw: 1. If I remove "virtual" from derived_t::get_value everything works as expected. 2. If I comment "cspc_ext.val_get_value(inst)" expression, than cspc_ext.const_ref_get_value(inst) works. I attached the source code. I am using compiler g++ 4.0.3 on Ubuntu, CVS version of boost. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ -------------- next part -------------- A non-text attachment was scrubbed... Name: cspc.cpp Type: text/x-c++src Size: 2792 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: test.py Type: text/x-python Size: 592 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Jamroot Type: application/octet-stream Size: 380 bytes Desc: not available URL: From markus at relix.de Thu Sep 14 04:39:19 2006 From: markus at relix.de (Markus Heller) Date: Thu, 14 Sep 2006 04:39:19 +0200 Subject: [C++-sig] extract character from PyObject (c++) Message-ID: <200609140439.20219.markus@relix.de> Dear List, I have this: a c++ PyObject which contains a unicode string. How can I isolate the individual unicode symbols from the string? Does anybody have sample code? Unfortunately I have only partly understood the definitions as given here: http://docs.python.org/api/unicodeObjects.html Thanks a lot! Markus From shiqinfeng at gmail.com Thu Sep 14 08:38:16 2006 From: shiqinfeng at gmail.com (Qinfeng(Javen) Shi ) Date: Thu, 14 Sep 2006 16:38:16 +1000 Subject: [C++-sig] how to wrap multi c++ files into python by pyste? Message-ID: Dear all, I know how to wrap a single c++ file into python by pyste? Does anybody how to wrap many c++ files into several *.so? We can't wrap every single file seperately because some types and functions used in it may be delared in other file. And puting everything into a huge single file is a ugly thing. Best wishes! Javen Research School of Information Sciences and Engineering Australian National University Locked Bag 8001 Canberra ACT 2601 -------------- next part -------------- An HTML attachment was scrubbed... URL: From roman.yakovenko at gmail.com Thu Sep 14 08:55:37 2006 From: roman.yakovenko at gmail.com (Roman Yakovenko) Date: Thu, 14 Sep 2006 09:55:37 +0300 Subject: [C++-sig] how to wrap multi c++ files into python by pyste? In-Reply-To: References: Message-ID: <7465b6170609132355l2b6e50d6s99082dd8e03df5e3@mail.gmail.com> On 9/14/06, Qinfeng(Javen) Shi wrote: > Dear all, > > I know how to wrap a single c++ file into python by pyste? Does anybody how > to wrap many c++ files into several *.so? Take a look on this: http://www.boost.org/libs/python/pyste/doc/running_pyste.html It seems that you should combine "multiple" and "generate-main" options. > We can't wrap every single file > seperately because some types and functions used in it may be delared in > other file. And puting everything into a huge single file is a ugly thing. I suggest you to look at Py++. Py++ is able to split generated code to few files, more over it is able to split generated code for single class to multiple files. Take a look on http://tinyurl.com/h33pn . Using Py++ you can generate code for a few modules from the same Python script. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ From shiqinfeng at gmail.com Thu Sep 14 09:31:01 2006 From: shiqinfeng at gmail.com (Qinfeng(Javen) Shi ) Date: Thu, 14 Sep 2006 17:31:01 +1000 Subject: [C++-sig] how to pass function pointer to a constructor of a template class when wrap it by pyste Message-ID: Dear all, I have a class (in hello.cc file) whose constructor assgins a value to a global function pointer. It is compiled by gcc and it works well. But it always reports an error when I used bjam to build the hello.cpp file (which is produced by pyste). If I remove the template, it works. But I do need the template. Does anybody know how to wrap it correctly? Any suggestion is appreciated. The hello.cc, hello.pyste, Jamfile are as following: /********************hello.cc*************/ #include float add(float a, float b) { return a+b; } float minus(float a, float b) { return a-b; } float (*op)(float a, float b) = add; template class cover_tree { P value; public: cover_tree(float (* metric)(float a, float b)) { op= metric; } cover_tree() { } }; int main() { float a,b,c; a = 1; b = 2; cover_tree ct2(minus); c = op(a,b); printf("%f\n",c); } /************************hello.pyste*********/ cover_tree = Template('cover_tree','hello.cc') cover = cover_tree("float") Function("main", "hello.cc") /************************Jamfile***********/ # This is the top of our own project tree project-root ; # Include definitions needed for Python modules import python ; extension hello # Declare a Python extension called hello : hello.cpp # requirements and dependencies for Boost.Python extensions