[C++-sig] How do I make correct wrappers to interfaces while using shared_ptrs?
I am trying to run this on Win32, using Stackless Python 2.6, and Boost 1.47. I am having a problem with passing a shared_ptr of a C++ object implementing a C++ interface to a wrapper of a Python object implementing a C++ interface. That's a mouthful, so I thought I'd simplify the code. The thing is, I can't seem to get the wrapping correct. If I can get this going, I can start adding complication to it and see what the problem really is. Basically, I have an interface that works with itself for communicating stuff. There is a C implementation of it, and a Python implementation of it. I have to write a wrapper. The Python implementation can communicate with instances of the C implementation, but not vice versa. When the C implementation calls the Python one, I get: Traceback (most recent call last): File "", line 1, in TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr The magic call is in the python script. Python script http://pastebin.com/DJ65tKEW Header http://pastebin.com/6BX8e6KA Source (Boost.Python declarations here) http://pastebin.com/s5YC1hyC I have done similar wrappers like this before so I'm just befuddled about why this time it hates me. The shared_ptrs are part of the larger problem I'm trying to reproduce, so I want to incorporate them into this test program. In the larger program, while doing a get_override() call on a wrapper to an interface, I get a segfault inside the Python DLLs while it tries to convert the shared_ptr. The last line I can see i shared_ptr_to_python.hpp: return converter::registered const&>::converters.to_python(&x); That's what I am eventually hoping to reproduce by shooting back and forth all this stuff. ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] storing weak_ptr to this in classes extended from python
On 02/03/2012 02:26 PM, Holger Brandsmeier wrote:
Dear list,
Note: I am actually using Teuchos::RCP instead of boost::shared_ptr
and boost::weak_ptr, but I already mirrored almost all the special
treatments in boost::python, and have been successfully using this for
a while. Everything that I write should actually apply to both
implementations in the same way.
I have a class that needs to store an RCP to itself to pass it along
to some classes that it creates, which might later need the RCP to
keep the original class alive. In C++ I implemented this by switching
the constructor to procted, and by having a static create() method
like this:
static RCP create(RCP< MeshT> mesh, Point
pol_deg_default)
{
RCP ret(new PfemSpaceT(mesh, pol_deg_default));
ret->setThisRCP(ret);
ret->init();
return ret;
}
The function setThisRCP() stores the shared point as a weak pointer.
When you call getThisRCP() the a strong RCP is returned from this weak
RCP. This is what you want as otherwise the class will never be
deleted.
The problem starts now as the same class is extended from python. I
mirror the same implementation in python as:
def __init__(self, mesh, pol_deg, cb_setDofEntity):
super(PfemSpaceStaticCond, self).__init__(mesh, pol_deg, False)
self.setThisRCP(self)
self.init()
Now I get serious problems with this call:
self.setThisRCP(self)
My understanding is, that the following happens:
1) the from-python converter creates an RCP with the use count of
one and a custom deletor
(boost::python::converter::shared_ptr_deleter).
2) the function setThisRCP gets called and stores a weak RCP
3) the control gets back to python and the use count of the RCP
drops to zero. The custom deletor dereferences the use count in
python.
Later calls to getThisRCP() that turn the weak RCP into a strong RCP
are then invalid. When python no longer references the class, it gets
deleted. Some C++ parts that used the RCP from getThisRCP() work on a
class that has been deleted and at some point the program crashes.
(Here maybe if I would use boost the program would crash already
earlier).
Do you have an idea how I can use the thisRCP paradigm together with
C++ classes that are extended from python?
It sounds like you need to ensure that instances created in Python
always use an RCP holder (even Python subclasses). I'd have thought
passing RCP as the holder template argument in the class_
definition would do that, but I'm not that familiar with how
smart-pointer holders interact with wrapper classes.
The second part is that you'd need to make sure #1 is replaced by having
Boost.Python look in the holder, find that it has an internal RCP, and
use that instead of creating a new temporary one. I know Boost.Python
can do that with shared_ptr at least some of the time, so I assume
you've set it up so that's possible with RCP too. You might try having
setThisRCP take a non-const reference to an RCP, so Boost.Python is
forced to use an lvalue converter and hence a non-temporary RCP.
Good luck!
Jim
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] make_constructor and extending from python
On 02/03/2012 03:13 PM, Holger Brandsmeier wrote:
Dear list,
how can I have a static member function that acts like a constructor
in a Wrapper, i.e. I have a class that I want to extend from python?
I have a wrapper class around a class (PfemSpace) that has this static
member functions:
static RCP create( ... )
{
RCP ret(new PfemSpaceWrapperT( ... ));
ret->setThisRCP(ret);
return ret;
}
This method is exported via
.def("__init__", make_constructor(&ClassWrapperT::create ) )
This works without errors, but when I use this from python via
class PfemSpaceStaticCond(PfemSpace):
def __init__(self, ...):
super(PfemSpaceStaticCond, self).__init__(...)
def visit_createFemData(self):
print '## [PfemSpaceStaticCond_init] visit_createFemData'
Here I call the constructor that I exported via make_constructor in
__init__(). Unfortunately the member function visit_createFemData that
I override in python never gets called. When I use a "real"
constructor instead of the one exported via make_constructor() then
the function visit_createFemData gets called.
I assume the error is somewhere that with a real constructor
boost::python can call an inplace constructor, while with my
make_constructor it can't. Is there some way to have the needed
functionality with make_constructor?
Note: today I came to the conclusion that I a read constructor instead
of a static member function is not an option for me due to the issues
I wrote in my previous mail "storing weak_ptr to this in classes
extended from python". That previous mail is actually from yesterday,
but it originally got rejected because I send it from a wrong email
address, so I'm sorry that you are receiving two mails from me today.
For a moment I was very happy that this "static constructor-like
function in the Wrapper class" would solve all my problems, but I am
still missing something.
I'm hoping my reply to your other email may give you a way forward,
because I think there's a possibility that you've run into a real
limitation of Boost.Python here.
The only thing I can think of is to override __new__, and not override
__init__; that might get the make_constructor version called.
But I'm just guessing. make_constructor, useful as it is, just doesn't
seem to really have the polish the rest of Boost.Python has, and I
wouldn't be surprised if it just doesn't work here. After all, if
you're wrapping a function that returns a smart pointer, there's no
guarantee that contains an instance of the wrapper class needed to
support Python-side polymorphism rather than just an instance of the C++
base class.
Jim
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] How do I make correct wrappers to interfaces while using shared_ptrs?
On 02/04/2012 11:11 AM, Adam Preble wrote: I am trying to run this on Win32, using Stackless Python 2.6, and Boost 1.47. I am having a problem with passing a shared_ptr of a C++ object implementing a C++ interface to a wrapper of a Python object implementing a C++ interface. That's a mouthful, so I thought I'd simplify the code. The thing is, I can't seem to get the wrapping correct. If I can get this going, I can start adding complication to it and see what the problem really is. Basically, I have an interface that works with itself for communicating stuff. There is a C implementation of it, and a Python implementation of it. I have to write a wrapper. The Python implementation can communicate with instances of the C implementation, but not vice versa. When the C implementation calls the Python one, I get: Traceback (most recent call last): File "", line 1, in TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr The magic call is in the python script. Python script http://pastebin.com/DJ65tKEW Header http://pastebin.com/6BX8e6KA Source (Boost.Python declarations here) http://pastebin.com/s5YC1hyC I have done similar wrappers like this before so I'm just befuddled about why this time it hates me. The shared_ptrs are part of the larger problem I'm trying to reproduce, so I want to incorporate them into this test program. In the larger program, while doing a get_override() call on a wrapper to an interface, I get a segfault inside the Python DLLs while it tries to convert the shared_ptr. The last line I can see i shared_ptr_to_python.hpp: return converter::registered const&>::converters.to_python(&x); That's what I am eventually hoping to reproduce by shooting back and forth all this stuff. If I understand your intend correctly, I think your class_ definition needs to be: class_,noncopyable> (right now you have class_) Jim ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
[C++-sig] boost::python bindings for protobuf
All, For those working with both protobuf and boost::python, I've written a protobuf plugin which generates boost::python wrappings for the protoc-generated C++ implementation. The rationale of the plugin (over, say, using the protoc experimental C++ python implementation) was a desire to directly wrap other C++ methods taking / returning protobuf message instances via boost::python. Presented in the hope that others find it useful: https://github.com/dademurphy/protobpl cheers, johnny ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] How do I make correct wrappers to interfaces while using shared_ptrs?
On Sat, Feb 4, 2012 at 10:46 AM, Jim Bosch wrote:
> If I understand your intend correctly, I think your class_ definition
> needs to be:
>
> class_,**noncopyable>
>
> (right now you have class_)
>
>
>
Something like this?
class_,
boost::noncopyable>("Communicatable")
I get burnt by the compiler when I try that:
d:\coding\boost_1_47_0\boost\python\object\pointer_holder.hpp(217): error
C2664: 'CommunicatableWrapper::CommunicatableWrapper(const
CommunicatableWrapper &)' : cannot convert parameter 1 from 'PyObject *' to
'const CommunicatableWrapper &'
Reason: cannot convert from 'PyObject *' to 'const
CommunicatableWrapper'
No constructor could take the source type, or constructor
overload resolution was ambiguous
It sounds like if I had a constructor that would take a PyObject *, that
would shut it up, but I have no idea what to make of such a thing.
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] How do I make correct wrappers to interfaces while using shared_ptrs?
On 02/04/2012 08:23 PM, Adam Preble wrote: On Sat, Feb 4, 2012 at 10:46 AM, Jim Bosch mailto:[email protected]>> wrote: If I understand your intend correctly, I think your class_ definition needs to be: class_,__noncopyable> (right now you have class_) Something like this? class_, boost::noncopyable>("Communicatable") I get burnt by the compiler when I try that: d:\coding\boost_1_47_0\boost\python\object\pointer_holder.hpp(217): error C2664: 'CommunicatableWrapper::CommunicatableWrapper(const CommunicatableWrapper &)' : cannot convert parameter 1 from 'PyObject *' to 'const CommunicatableWrapper &' Reason: cannot convert from 'PyObject *' to 'const CommunicatableWrapper' No constructor could take the source type, or constructor overload resolution was ambiguous It sounds like if I had a constructor that would take a PyObject *, that would shut it up, but I have no idea what to make of such a thing. Oh, you're right. I was confusing the manual way of doing Python-side polymorphism (derived-class holders) with the more automatic (and better) way you're doing it (with wrapper). Your original code was fine in that regard. Anyhow, looking closer, here's what you need to do: - Put your code back to what it was before I told you to change it. - Add another line, after the class wrappers: register_ptr_to_python< boost::shared_ptr >(); That explicitly registers a shared_ptr converter for Communicatable. I'm not sure why Boost.Python doesn't automatically do that when you register converters for its derived classes (those are registered by putting the shared_pr types in the template parameters to class_). It might just be an oversight, or it might be that doing the base class registration automatically would cause problems in some contexts. Jim ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] How do I make correct wrappers to interfaces while using shared_ptrs?
On Sat, Feb 4, 2012 at 8:48 PM, Jim Bosch wrote: > Oh, you're right. I was confusing the manual way of doing Python-side > polymorphism (derived-class holders) with the more automatic (and better) > way you're doing it (with wrapper). Your original code was fine in that > regard. > > Anyhow, looking closer, here's what you need to do: > > - Put your code back to what it was before I told you to change it. > > - Add another line, after the class wrappers: > > register_ptr_to_python< boost::shared_ptr<**Communicatable> >(); > > That explicitly registers a shared_ptr converter for Communicatable. I'm > not sure why Boost.Python doesn't automatically do that when you register > converters for its derived classes (those are registered by putting the > shared_pr types in the template parameters to class_). It might just be an > oversight, or it might be that doing the base class registration > automatically would cause problems in some contexts. > > > The appears to do the trick. I'm wondering--how do you figure out stuff like that? That isn't the kind of thing that could have just occurred to me. This little test program works, but so far I haven't resolved the crash in my more complicated code that's coming a Python subclass of a C class trying to get a callback from Python instance of a C class . . . it's rough even explaining it. I'll have to review my code and make sure I'm doing that in all the right places. Either I get it working because of these little things here, or I'll be back with a modification of this source to show the problem with shared_ptr conversion that I was seeing. ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
