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 | [email protected] | 070-310 47 07 ___ Cplusplus-sig mailing list [email protected] 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
[email protected]
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
[email protected]
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
> [email protected]
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>
--
Renato Araujo Oliveira Filho
___
Cplusplus-sig mailing list
[email protected]
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
[email protected]
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
[email protected]
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
[email protected]
http:// mail.python.org/mailman/listinfo/cplusplus-sig
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
