Re: [C++-sig] Differences between 32-bit and 64-bit python25.lib
On Mon, Jun 22, 2009 at 09:52:35AM +0300, Jesse Lehrman wrote: > It seems that most of the exports in the 32-bit version have a preceding > underscore while in the 64-bit version they don't. For example: > > python25.lib 32-bit: > _PyFloat_AsDouble > > python25.lib 64-bit: > PyFloat_AsDouble > > Does anybody have an idea of why this is done and how I can get around it? x86 has a whole slew of calling conventions, and in order to disambiguate between them, symbols are decorated according to the convention used [1]. In this case, a leading underscore means it's cdecl. With x86_64, there's a new and shiny calling convention [2], replacing all the old ones. As there's only one, there's no need to decorate that one with anything in a symbol, thus the lack of _ in your 64-bit symbol. This is all from a Windows perspective of course, as that's your context. As for getting things to do the right thing, I'm unsure. [1] http://blogs.msdn.com/oldnewthing/archive/2004/01/08/48616.aspx [2] http://blogs.msdn.com/freik/archive/2005/03/17/398200.aspx -- Lars Viklund | z...@acc.umu.se | 070-310 47 07 ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
[C++-sig] embedding python in C++: exceptions, a newbie Q
Hi, I am trying to use boost.python to wrap some classes in an application, and have python embedded in my app and make some instances from the application accessible thru simple script. I got the impression that with boost python it should be quite simple for basics, but I cannot have a simple code as bellow run: 1. If I uncomment the //import("MyModule"); I get a runtime error - and an application crash. And without it- I get an exception that the C++ class CMyWrap is not associated with a python class. 2. If I just try to do a simpler thing like //exec("dir(__main__)", main_namespace); I get "bad argument to an internal function" as an exception. I use python26_d.dll/ python26_d.lib and libboost_python-vc90-mt-1_39.lib (boost 1.39 compiled as static lib). Can you please help? Can you refer me to any documentation that may help? TIA, Yuv. class CMyWrap { public: string Greet() { return "I'm the dude!?"; } }; class CppClass { public: int getNum() { return 7; } }; BOOST_PYTHON_MODULE(MyModule) { class_("CMyWrap") .def("greet", &CMyWrap::Greet); } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; CMyWrap myObj; try { PyImport_AppendInittab( "MyModule", &initMyModule); Py_Initialize(); object main_module = import("__main__"); object main_namespace = main_module.attr("__dict__"); //import("MyModule"); //exec("dir(__main__)", main_namespace); main_namespace["myObj"] = ptr(&myObj); } catch( error_already_set ) { PyErr_Print(); } Py_Finalize(); return nRetCode; } -- Yuval Nahmany cell. 054-2020665 ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
[C++-sig] wchar_t* type conversion
Hello, I'm new to Boost::Python and am encountering a problem that seem to be quite common: I need to expose a class to C++ whose constructor takes a wchar_t* as a parameter. The problem is that there is no default type converter from wchar_t to python and vice-versa. I wanted to know if there was a standard way of doing this. Or if anyone could point me to an implementation of this type conversion. So far I'm doing this (based on the faq): struct wchar_t_to_python_str { static PyObject* convert(wchar_t* const& w) { string s = ""; wchar_t* w2 = w; while(*w2++ != 0){ s += *w2; } return boost::python::incref(boost::python::object(s).ptr()); } }; struct wchar_t_from_python_str { wchar_t_from_python_str() { boost::python::converter::registry::push_back( &convertible, &construct, boost::python::type_id()); } static void* convertible(PyObject* obj_ptr) { if (!PyString_Check(obj_ptr)) return 0; return obj_ptr; } static void construct( PyObject* obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data) { const char* value = PyString_AsString(obj_ptr); Py_ssize_t l = PyString_Size(obj_ptr); if (value == 0) boost::python::throw_error_already_set(); void* storage = ( (boost::python::converter::rvalue_from_python_storage*) data)->storage.bytes; wchar_t* w = new wchar_t[l]; for(int i=0;iconvertible = w; } }; void init_module() { to_python_converter(); wchar_t_from_python_str(); } BOOST_PYTHON_MODULE(queryparser){ init_module(); } But it doesn't seem to be working. It compiles, but python doesn't understand the conversion. Any thoughts? Thanks in advance! -- Nicolas Lara Linux user #380134 http://nicolas-lara.blogspot.com/ Public key id: 0x152e7713 at http://subkeys.pgp.net/ ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] wchar_t* type conversion
Hi Nicolas, Can you send a simple example, where the convention fail (c++ to python or python to c++)? What kind of test you are running? BR Renato On Mon, Jun 22, 2009 at 8:31 AM, Nicolas Lara wrote: > Hello, > I'm new to Boost::Python and am encountering a problem that seem to be > quite common: I need to expose a class to C++ whose constructor takes > a wchar_t* as a parameter. > The problem is that there is no default type converter from wchar_t to > python and vice-versa. > > I wanted to know if there was a standard way of doing this. Or if > anyone could point me to an implementation of this type conversion. > > So far I'm doing this (based on the faq): > > struct wchar_t_to_python_str > { > static PyObject* convert(wchar_t* const& w) > { > string s = ""; > wchar_t* w2 = w; > while(*w2++ != 0){ > s += *w2; > } > return boost::python::incref(boost::python::object(s).ptr()); > } > }; > > struct wchar_t_from_python_str > { > wchar_t_from_python_str() > { > boost::python::converter::registry::push_back( > &convertible, > &construct, > boost::python::type_id()); > } > > static void* convertible(PyObject* obj_ptr) > { > if (!PyString_Check(obj_ptr)) return 0; > return obj_ptr; > } > > static void construct( > PyObject* obj_ptr, > > boost::python::converter::rvalue_from_python_stage1_data* data) > { > const char* value = PyString_AsString(obj_ptr); > Py_ssize_t l = PyString_Size(obj_ptr); > if (value == 0) boost::python::throw_error_already_set(); > void* storage = ( > > (boost::python::converter::rvalue_from_python_storage*) > data)->storage.bytes; > > wchar_t* w = new wchar_t[l]; > for(int i=0;i w[i] = value[i]; > } > data->convertible = w; > } > }; > void init_module() > { > to_python_converter(); > wchar_t_from_python_str(); > } > > BOOST_PYTHON_MODULE(queryparser){ > init_module(); > } > > But it doesn't seem to be working. It compiles, but python doesn't > understand the conversion. > Any thoughts? > > > Thanks in advance! > > -- > Nicolas Lara > Linux user #380134 > http://nicolas-lara.blogspot.com/ > Public key id: 0x152e7713 at http://subkeys.pgp.net/ > ___ > Cplusplus-sig mailing list > Cplusplus-sig@python.org > http://mail.python.org/mailman/listinfo/cplusplus-sig > -- Renato Araujo Oliveira Filho ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] wchar_t* type conversion
Hi Renato, Thanks for the reply. Here's some test code. (I pasted it to make it more friendly =) http://paste.pocoo.org/show/124521/ Testing it in python: http://paste.pocoo.org/show/124523/ Thanks in advance! Best Regards For the archives: === test.cpp #include "CLucene.h" #include #include using namespace boost::python; struct wchar_t_to_python_str { static PyObject* convert(wchar_t* const& w) { string s = ""; wchar_t* w2 = w; while(*w2++ != 0){ s += *w2; } return boost::python::incref(boost::python::object(s).ptr()); } }; struct wchar_t_from_python_str { wchar_t_from_python_str() { boost::python::converter::registry::push_back( &convertible, &construct, boost::python::type_id()); } static void* convertible(PyObject* obj_ptr) { if (!PyString_Check(obj_ptr)) return 0; return obj_ptr; } static void construct( PyObject* obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data) { const char* value = PyString_AsString(obj_ptr); Py_ssize_t l = PyString_Size(obj_ptr); if (value == 0) boost::python::throw_error_already_set(); void* storage = ( (boost::python::converter::rvalue_from_python_storage*) data)->storage.bytes; wchar_t* w = new wchar_t[l]; for(int i=0;iconvertible = w; } }; void init_module() { to_python_converter(); wchar_t_from_python_str(); } struct Test { Test(){} wchar_t * testReturnValue(string s){ wchar_t *p=new wchar_t[s.size()]; for(string::size_type i=0; i("Test") //.def("testReturnValue", &Test::testReturnValue) // <- desn't compile .def("testArgument", &Test::testArgument); ; } testing it in python >>> import test >>> t = test.Test() >>> t.testArgument(u"") --- ArgumentError Traceback (most recent call last) /home/.../build/ in () ArgumentError: Python argument types in Test.testArgument(Test, unicode) did not match C++ signature: testArgument(Test {lvalue}, wchar_t*) >>> t.testArgument("") --- ArgumentError Traceback (most recent call last) /home/.../build/ in () ArgumentError: Python argument types in Test.testArgument(Test, str) did not match C++ signature: testArgument(Test {lvalue}, wchar_t*) >>> from ctypes import c_wchar_p >>> c_wchar_p("hello") >>> c_wchar_p(u'hello') >>> w = c_wchar_p("hello") >>> t.testArgument(w) --- ArgumentError Traceback (most recent call last) /home/nicolas/devel/CyLucene/build/ in () ArgumentError: Python argument types in Test.testArgument(Test, c_wchar_p) did not match C++ signature: testArgument(Test {lvalue}, wchar_t*) On Mon, Jun 22, 2009 at 1:48 PM, Renato Araujo wrote: > Hi Nicolas, > > Can you send a simple example, where the convention fail (c++ to > python or python to c++)? What kind of test you are running? > > BR > Renato > > > > On Mon, Jun 22, 2009 at 8:31 AM, Nicolas Lara wrote: >> Hello, >> I'm new to Boost::Python and am encountering a problem that seem to be >> quite common: I need to expose a class to C++ whose constructor takes >> a wchar_t* as a parameter. >> The problem is that there is no default type converter from wchar_t to >> python and vice-versa. >> >> I wanted to know if there was a standard way of doing this. Or if >> anyone could point me to an implementation of this type conversion. >> >> So far I'm doing this (based on the faq): >> >> struct wchar_t_to_python_str >> { >> static PyObject* convert(wchar_t* const& w) >> { >> string s = ""; >> wchar_t* w2 = w; >> while(*w2++ != 0){ >> s += *w2; >> } >> return boost::python::incref(boost::python::object(s).ptr()); >> } >> }; >> >> struct wchar_t_from_python_str >> { >> wchar_t_from_python_str() >> { >> boost::python::converter::registry::push_back( >> &convertible, >> &construct, >> boost::python::type_id()); >> } >> >> static void* convertible(PyObject* obj_ptr) >> { >> if (!PyString_Check(obj_ptr)) return 0; >> return obj_ptr; >> } >> >> static void construct( >> PyObject* obj_ptr, >> >> boost::python::converter::rvalue_from_python_stage1_data* data) >> { >> const char* value = PyString_AsString(obj_ptr); >> Py_ssize_t l = PyString_Size(obj_ptr); >> if (value == 0) boost::python::throw_error_already_set(); >> void* storage = ( >> >> (boost::python::converter::rvalue_from_python_storage*) >> data)->storage.bytes; >> >> wchar_t* w = new wchar_t[l]; >> for(int i=0;i> w[i] = value[i]; >> } >
Re: [C++-sig] wchar_t* type conversion
Hi Nicolas At my first look I get this working changing the register function: << to_python_converter(); >> to_python_converter(); << static PyObject* convert(wchar_t* const& w) >> static PyObject* convert(wchar_t const& w) <> wchar_t w2 = w; >> while(w2++ != 0){ >> s += w2; and the function signature: << void testArgument(wchar_t * w){ >> void testArgument(const wchar_t &w){ this make everything works fine: I don't know how get this working with wchar_t* in function signature. Maybe create a class_ for w_char_t. On Mon, Jun 22, 2009 at 2:27 PM, Nicolas Lara wrote: > Hi Renato, > Thanks for the reply. Here's some test code. (I pasted it to make it > more friendly =) > http://paste.pocoo.org/show/124521/ > > Testing it in python: http://paste.pocoo.org/show/124523/ > > Thanks in advance! > Best Regards > > For the archives: > > === test.cpp > > #include "CLucene.h" > #include > #include > > using namespace boost::python; > > struct wchar_t_to_python_str > { > static PyObject* convert(wchar_t* const& w) > { > string s = ""; > wchar_t* w2 = w; > while(*w2++ != 0){ > s += *w2; > } > return boost::python::incref(boost::python::object(s).ptr()); > } > }; > > struct wchar_t_from_python_str > { > wchar_t_from_python_str() > { > boost::python::converter::registry::push_back( > &convertible, > &construct, > boost::python::type_id()); > } > > static void* convertible(PyObject* obj_ptr) > { > if (!PyString_Check(obj_ptr)) return 0; > return obj_ptr; > } > > static void construct( > PyObject* obj_ptr, > > boost::python::converter::rvalue_from_python_stage1_data* data) > { > const char* value = PyString_AsString(obj_ptr); > Py_ssize_t l = PyString_Size(obj_ptr); > if (value == 0) boost::python::throw_error_already_set(); > void* storage = ( > > (boost::python::converter::rvalue_from_python_storage*) > data)->storage.bytes; > > wchar_t* w = new wchar_t[l]; > for(int i=0;i w[i] = value[i]; > } > data->convertible = w; > } > }; > > void init_module() > { > to_python_converter(); > wchar_t_from_python_str(); > } > > > struct Test { > Test(){} > > wchar_t * testReturnValue(string s){ > wchar_t *p=new wchar_t[s.size()]; > for(string::size_type i=0; i p[i]=s[i]; > return p; > } > > void testArgument(wchar_t * w){ > printf("ok\n"); > } > }; > > > BOOST_PYTHON_MODULE(test){ > init_module(); > class_("Test") > //.def("testReturnValue", &Test::testReturnValue) // <- desn't compile > .def("testArgument", &Test::testArgument); > ; > > } > > testing it in python import test > t = test.Test() > t.testArgument(u"") > --- > ArgumentError Traceback (most recent call last) > > /home/.../build/ in () > > ArgumentError: Python argument types in > Test.testArgument(Test, unicode) > did not match C++ signature: > testArgument(Test {lvalue}, wchar_t*) > t.testArgument("") > --- > ArgumentError Traceback (most recent call last) > > /home/.../build/ in () > > ArgumentError: Python argument types in > Test.testArgument(Test, str) > did not match C++ signature: > testArgument(Test {lvalue}, wchar_t*) > from ctypes import c_wchar_p > c_wchar_p("hello") c_wchar_p(u'hello') > w = c_wchar_p("hello") > t.testArgument(w) > --- > ArgumentError Traceback (most recent call last) > > /home/nicolas/devel/CyLucene/build/ in () > > ArgumentError: Python argument types in > Test.testArgument(Test, c_wchar_p) > did not match C++ signature: > testArgument(Test {lvalue}, wchar_t*) > > > On Mon, Jun 22, 2009 at 1:48 PM, Renato Araujo wrote: >> Hi Nicolas, >> >> Can you send a simple example, where the convention fail (c++ to >> python or python to c++)? What kind of test you are running? >> >> BR >> Renato >> >> >> >> On Mon, Jun 22, 2009 at 8:31 AM, Nicolas Lara wrote: >>> Hello, >>> I'm new to Boost::Python and am encountering a problem that seem to be >>> quite common: I need to expose a class to C++ whose constructor takes >>> a wchar_t* as a parameter. >>> The problem is that there is no default type converter from wchar_t to >>> python and vice-versa. >>> >>> I wanted to know if there was a standard way of doing this. Or if >>> anyone could point me to an implementation of this type conversion. >>> >>> So far I'm doing this (based on the faq): >>> >>> struct wchar_t_to_python_str >>> { >>> static PyObject* convert(wchar_t* const& w) >>> { >>> string s = ""; >>> wchar_t* w2 = w; >>>
Re: [C++-sig] wchar_t* type conversion
Thanks! I'm trying to create an interface for a third party library, so I can't actually change it. I also tried using ctypes.pointer but didn't work either. I'll probably need to create a wrapper that does the type conversion. Thanks again Renato! If anyone knows how to make it work with wchar_t* i'd appreciate it! On Mon, Jun 22, 2009 at 11:57 AM, Renato Araujo wrote: > Hi Nicolas > > At my first look I get this working changing the register function: > > << to_python_converter(); >>> to_python_converter(); > > << static PyObject* convert(wchar_t* const& w) >>> static PyObject* convert(wchar_t const& w) > > << wchar_t* w2 = w; > << while(*w2++ != 0){ > << s += *w2; >>> wchar_t w2 = w; >>> while(w2++ != 0){ >>> s += w2; > > and the function signature: > > << void testArgument(wchar_t * w){ >>> void testArgument(const wchar_t &w){ > > this make everything works fine: > > I don't know how get this working with wchar_t* in function signature. > Maybe create a class_ for w_char_t. > > > > On Mon, Jun 22, 2009 at 2:27 PM, Nicolas Lara wrote: >> Hi Renato, >> Thanks for the reply. Here's some test code. (I pasted it to make it >> more friendly =) >> http://paste.pocoo.org/show/124521/ >> >> Testing it in python: http://paste.pocoo.org/show/124523/ >> >> Thanks in advance! >> Best Regards >> >> For the archives: >> >> === test.cpp >> >> #include "CLucene.h" >> #include >> #include >> >> using namespace boost::python; >> >> struct wchar_t_to_python_str >> { >> static PyObject* convert(wchar_t* const& w) >> { >> string s = ""; >> wchar_t* w2 = w; >> while(*w2++ != 0){ >> s += *w2; >> } >> return boost::python::incref(boost::python::object(s).ptr()); >> } >> }; >> >> struct wchar_t_from_python_str >> { >> wchar_t_from_python_str() >> { >> boost::python::converter::registry::push_back( >> &convertible, >> &construct, >> boost::python::type_id()); >> } >> >> static void* convertible(PyObject* obj_ptr) >> { >> if (!PyString_Check(obj_ptr)) return 0; >> return obj_ptr; >> } >> >> static void construct( >> PyObject* obj_ptr, >> >> boost::python::converter::rvalue_from_python_stage1_data* data) >> { >> const char* value = PyString_AsString(obj_ptr); >> Py_ssize_t l = PyString_Size(obj_ptr); >> if (value == 0) boost::python::throw_error_already_set(); >> void* storage = ( >> >> (boost::python::converter::rvalue_from_python_storage*) >> data)->storage.bytes; >> >> wchar_t* w = new wchar_t[l]; >> for(int i=0;i> w[i] = value[i]; >> } >> data->convertible = w; >> } >> }; >> >> void init_module() >> { >> to_python_converter(); >> wchar_t_from_python_str(); >> } >> >> >> struct Test { >> Test(){} >> >> wchar_t * testReturnValue(string s){ >> wchar_t *p=new wchar_t[s.size()]; >> for(string::size_type i=0; i> p[i]=s[i]; >> return p; >> } >> >> void testArgument(wchar_t * w){ >> printf("ok\n"); >> } >> }; >> >> >> BOOST_PYTHON_MODULE(test){ >> init_module(); >> class_("Test") >> //.def("testReturnValue", &Test::testReturnValue) // <- desn't compile >> .def("testArgument", &Test::testArgument); >> ; >> >> } >> >> testing it in python > import test >> > t = test.Test() >> > t.testArgument(u"") >> --- >> ArgumentError Traceback (most recent call last) >> >> /home/.../build/ in () >> >> ArgumentError: Python argument types in >> Test.testArgument(Test, unicode) >> did not match C++ signature: >> testArgument(Test {lvalue}, wchar_t*) >> > t.testArgument("") >> --- >> ArgumentError Traceback (most recent call last) >> >> /home/.../build/ in () >> >> ArgumentError: Python argument types in >> Test.testArgument(Test, str) >> did not match C++ signature: >> testArgument(Test {lvalue}, wchar_t*) >> > from ctypes import c_wchar_p >> > c_wchar_p("hello") > c_wchar_p(u'hello') >> > w = c_wchar_p("hello") >> > t.testArgument(w) >> --- >> ArgumentError Traceback (most recent call last) >> >> /home/nicolas/devel/CyLucene/build/ in () >> >> ArgumentError: Python argument types in >> Test.testArgument(Test, c_wchar_p) >> did not match C++ signature: >> testArgument(Test {lvalue}, wchar_t*) >> >> >> On Mon, Jun 22, 2009 at 1:48 PM, Renato Araujo wrote: >>> Hi Nicolas, >>> >>> Can you send a simple example, where the convention fail (c++ to >>> python or python to c++)? What kind of test you are running? >>> >>> BR >>> Renato >>> >>> >>> >>> On Mon, Jun 22, 2009 at 8:31 AM, Nicolas Lara wrote: Hello, I'm new to Boost::Python and am encountering
[C++-sig] pybindgen: Why does pybindgen want to call constructors for a singleton class?
I'm looking at wrapping a C++ singleton with pybindgen, and it seems that if I expose the method for getting the instance to python the generated code wants to call a copy constructor, which seems wrong to me. If for instance I define a class "A" as a singleton: class A { public: static A* instancePtr() { if (A::mInstancePtr == 0) A::mInstancePtr = new A; return mInstancePtr; } private: A(); A(const A& rhs); A& operator=(const A& rhs); static A* mInstancePtr; }; and I wrap A and its instance method like so: mod = Module("singleton_example") mod.add_include('"singleton_example.hh"') x = mod.add_class("A", is_singleton=True) x.add_method("instancePtr", retval("A*", caller_owns_return=False), []) pybindgen generates the following code for the instancePtr method: PyObject * _wrap_PyA_instancePtr(PyA *self) { PyObject *py_retval; A *retval; PyA *py_A; retval = self->obj->instancePtr(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_A = PyObject_New(PyA, &PyA_Type); py_A->obj = new A(*retval); py_retval = Py_BuildValue((char *) "N", py_A); return py_retval; } As you can see it is trying to construct a new object with a copy of the A retval parameter (the line that reads "py_A->obj = new A(*retval);". This is of course forbidden because all of A's constructors are private -- as a singleton we don't want anyone calling constructors on this object. Moreover, since I exposed "instancePtr" as returning a pointer I did not expect any copies to be generated anyway -- I'd like to see the pointer "retval" sent back directly (even if this wasn't a singleton). Am I missing some syntax here to prevent pybindgen from trying to make these copies? Thanks! Mike. ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] pybindgen: Why does pybindgen want to call constructors for a singleton class?
2009/6/22 J. Michael Owen > I'm looking at wrapping a C++ singleton with pybindgen, and it seems that > if I expose the method for getting the instance to python the generated code > wants to call a copy constructor, which seems wrong to me. If for instance > I define a class "A" as a singleton: > > class A { > public: > static A* instancePtr() { >if (A::mInstancePtr == 0) A::mInstancePtr = new A; >return mInstancePtr; > } > private: > A(); > A(const A& rhs); > A& operator=(const A& rhs); > static A* mInstancePtr; > }; > > and I wrap A and its instance method like so: > > mod = Module("singleton_example") > mod.add_include('"singleton_example.hh"') > x = mod.add_class("A", is_singleton=True) > x.add_method("instancePtr", retval("A*", caller_owns_return=False), []) > > pybindgen generates the following code for the instancePtr method: > > PyObject * > _wrap_PyA_instancePtr(PyA *self) > { >PyObject *py_retval; >A *retval; >PyA *py_A; > >retval = self->obj->instancePtr(); >if (!(retval)) { >Py_INCREF(Py_None); >return Py_None; >} >py_A = PyObject_New(PyA, &PyA_Type); >py_A->obj = new A(*retval); >py_retval = Py_BuildValue((char *) "N", py_A); >return py_retval; > } > > As you can see it is trying to construct a new object with a copy of the A > retval parameter (the line that reads "py_A->obj = new A(*retval);". This > is of course forbidden because all of A's constructors are private -- as a > singleton we don't want anyone calling constructors on this object. > Moreover, since I exposed "instancePtr" as returning a pointer I did not > expect any copies to be generated anyway -- I'd like to see the pointer > "retval" sent back directly (even if this wasn't a singleton). Am I missing > some syntax here to prevent pybindgen from trying to make these copies? It tries to copy because you say caller_owns_return=False, pybindgen needs to copy the object so that the wrapper can own the object. What you can do here is use caller_owns_return=True instead of False. It's OK in this case; because of the is_singleton option, the C++ wrapped object will never be freed when the wrapper is destroyed. -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] pybindgen: Why does pybindgen want to call constructors for a singleton class?
Ah, I see! That does the trick! Thank you very much. I was clearly confused about what "caller_owns_return" meant -- I had it backwards. Mike. On Jun 22, 2009, at 5:11 PM, Gustavo Carneiro wrote: 2009/6/22 J. Michael Owen I'm looking at wrapping a C++ singleton with pybindgen, and it seems that if I expose the method for getting the instance to python the generated code wants to call a copy constructor, which seems wrong to me. If for instance I define a class "A" as a singleton: class A { public: static A* instancePtr() { if (A::mInstancePtr == 0) A::mInstancePtr = new A; return mInstancePtr; } private: A(); A(const A& rhs); A& operator=(const A& rhs); static A* mInstancePtr; }; and I wrap A and its instance method like so: mod = Module("singleton_example") mod.add_include('"singleton_example.hh"') x = mod.add_class("A", is_singleton=True) x.add_method("instancePtr", retval("A*", caller_owns_return=False), []) pybindgen generates the following code for the instancePtr method: PyObject * _wrap_PyA_instancePtr(PyA *self) { PyObject *py_retval; A *retval; PyA *py_A; retval = self->obj->instancePtr(); if (!(retval)) { Py_INCREF(Py_None); return Py_None; } py_A = PyObject_New(PyA, &PyA_Type); py_A->obj = new A(*retval); py_retval = Py_BuildValue((char *) "N", py_A); return py_retval; } As you can see it is trying to construct a new object with a copy of the A retval parameter (the line that reads "py_A->obj = new A(*retval);". This is of course forbidden because all of A's constructors are private -- as a singleton we don't want anyone calling constructors on this object. Moreover, since I exposed "instancePtr" as returning a pointer I did not expect any copies to be generated anyway -- I'd like to see the pointer "retval" sent back directly (even if this wasn't a singleton). Am I missing some syntax here to prevent pybindgen from trying to make these copies? It tries to copy because you say caller_owns_return=False, pybindgen needs to copy the object so that the wrapper can own the object. What you can do here is use caller_owns_return=True instead of False. It's OK in this case; because of the is_singleton option, the C++ wrapped object will never be freed when the wrapper is destroyed. -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http:// mail.python.org/mailman/listinfo/cplusplus-sig ___ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig