[C++-sig] Passing objects between python / c++

Mark Williams mark at image-engine.com
Mon Oct 23 22:58:10 CEST 2006


I'm having a few problems passing objects in and out of Python/C++ via boost.python, which are probably explained best by the example and test cases below.

I have a trivial class "Base", and some functions which allows reference-counted instances of this class to be stored/retrieved to/from a static variable. 

Firstly, I derive class "Derived" from "Base" within Python, and "store" an instance of Derived in the C++ static. When
I then "retrieve" this object in Python I find that it's no longer of type "Derived", but of type "Base":

c = Derived()
store(c)
d = retrieve()
self.assertEqual( type(c), type(d) )         # FAILS

Secondly, I store and then immediately retrieve an instance of "Base". I find that boost returns me a different Python object.
I'm not surprised that this happens, but cannot find a CallPolicy which works:

c = Base()
store(c)
d = retrieve()
self.assert_( c is d )         # FAILS

Is it possible to fix either of these problems by modifiying my boost.python bindings alone?

Thanks in advance,

Mark


////////////////////////////////////////////////
 
class Base : public RefCounted /* RefCounted is my own implementation of a simple reference counting class */
{
	public:
	Base() {};
};
typedef boost::intrusive_ptr<Base> BasePtr;

template<typename T>
struct GlobalsTest
{
	static boost::intrusive_ptr<T> g_object ;
	
	static boost::intrusive_ptr<T> retrieve()
	{
		return g_object;
	}

	static void store( const boost::intrusive_ptr<T> &o)
	{
		g_object = o;
	}
};

BOOST_PYTHON_MODULE(myModule)
{
	class_< Base, BasePtr>("Base");
	def("store", & GlobalsTest<Base>::store );
	def("retrieve", & GlobalsTest<Base>::retrieve );
}

//////////////////////////////////////////////////////////////////////////////////////////////////

import unittest

from myModule import *

class Derived(Base):
	def methodInDerived(self):
		return 12
		

class TestBoostPython(unittest.TestCase):
	def test1(self):
		
		c = Derived()
		self.assertEqual( c.methodInDerived(), 12 )
		
		store(c)
		d = retrieve()
		
		self.assertEqual( type(c), type(d) )
		self.assert_( c is d )
		
	def test2(self):
		
		c = Base()		
		
		store(c)
		d = retrieve()
		
		self.assertEqual( type(c), type(d) )
		self.assert_( c is d )
				
		
if __name__ == "__main__":
	unittest.main()   
		
/////////////////////////////////////////////////////////////////////////////////


test1 (__main__.TestBoostPython) ... FAIL
test2 (__main__.TestBoostPython) ... FAIL

======================================================================
FAIL: test1 (__main__.TestBoostPython)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/boostPython.py", line 19, in test1
    self.assertEqual( type(c), type(d) )
AssertionError: <class '__main__.Derived'> != <class 'myModule.Base'>

======================================================================
FAIL: test2 (__main__.TestBoostPython)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/boostPython.py", line 30, in test2
    self.assert_( c is d )
AssertionError

----------------------------------------------------------------------







More information about the Cplusplus-sig mailing list