Revision: 863
http://svn.sourceforge.net/pygccxml/?rev=863&view=rev
Author: roman_yakovenko
Date: 2007-01-09 13:24:49 -0800 (Tue, 09 Jan 2007)
Log Message:
-----------
adding example of auto conversion
Modified Paths:
--------------
pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/auto_conversion.cpp
pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/test.py
Modified: pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/auto_conversion.cpp
===================================================================
--- pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/auto_conversion.cpp 2007-01-09 09:29:03 UTC (rev 862)
+++ pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/auto_conversion.cpp 2007-01-09 21:24:49 UTC (rev 863)
@@ -1,40 +1,93 @@
#include "boost/python.hpp"
#include "boost/python/object.hpp" //len function
#include "boost/python/ssize_t.hpp" //ssize_t type definition
-#include <string>
+#include "boost/python/detail/none.hpp"
+//This example is very similar to one found in Boost.Python FAQs:
+//How can I automatically convert my custom string type to and from a Python string?
+//http://www.boost.org/libs/python/doc/v2/faq.html#custom_string
+//I will introduce another example with detailed explanation.
+
+//Simple class, which describes a point in 3D. I don't want to export the class.
+//Instead of this I want Python user pass tuple as argument to all functions
+//that expects point3d_t class instance and Boost.Python will automaticly handle
+//the conversion. Same conversion should be applied on functions, which returns
+//point3d_t class instance
+
struct point3d_t{
- point3d_t()
- : x(0), y(0), z(0)
+ explicit point3d_t(int x_=0, int y_=0, int z_=0)
+ : x(x_), y(y_), z(z_)
{}
-
+
+ bool operator==( const point3d_t& other ) const{
+ return x == other.x && y == other.y && z == other.z;
+ }
+
int x, y, z;
};
+
+point3d_t point_ret_val_000() {
+ return point3d_t();
+}
+
+point3d_t point_ret_val_101() {
+ return point3d_t(1,0,1);
+}
+
+point3d_t& point_ret_ref_010(){
+ static point3d_t pt( 0,1,0 );
+ return pt;
+}
+
+point3d_t* point_ret_ptr_110(){
+ static point3d_t pt( 1,1,0 );
+ return &pt;
+}
+
+bool test_point_val_000( point3d_t pt ){
+ return pt == point3d_t( 0,0,0 );
+}
+
+bool test_point_cref_010( const point3d_t& pt ){
+ return pt == point3d_t( 0,1,0 );
+}
+
+bool test_point_ref_110( point3d_t& pt ){
+ return pt == point3d_t( 1,1,0 );
+}
+
+bool test_point_ptr_101( point3d_t* pt ){
+ return pt && *pt == point3d_t( 1,0,1 );
+}
+
+
namespace bpl = boost::python;
namespace point3d_conversion{
struct to_tuple{
-
- to_tuple(){
- bpl::to_python_converter< point3d_t, to_tuple>();
- }
-
+ //"To Python" conversion is pretty simple:
+ //Using Python C API create an object and than manually fill it with data.
+ //In this case Boost.Python provides a convenience API for tuple construction.
+ //I don't see any reason not to use it.
static PyObject* convert(point3d_t const& pt){
return bpl::incref( bpl::make_tuple( pt.x, pt.y, pt.z ).ptr() );
}
-
};
struct from_tuple{
-
+ //"From Python" conversion is more complex. Memory managment is the main
+ //reason for this.
+
+ //The first step in conversion from the Python object is to check whether
+ //the object is the right one.
static void* convertible(PyObject* py_seq){
if( !PySequence_Check( py_seq ) ){
//check that the argument is a sequence
return 0;
}
- bpl::object seq = bpl::object( bpl::handle<>( py_seq ) );
+ bpl::object seq = bpl::object( bpl::handle<>( bpl::borrowed( py_seq ) ) );
bpl::ssize_t size = bpl::len( seq );
if( 3 != size ){
return 0;
@@ -79,7 +132,7 @@
//it later
data->convertible = memory_chunk;
- bpl::object seq = bpl::object( bpl::handle<>( py_seq ) );
+ bpl::object seq = bpl::object( bpl::handle<>( bpl::borrowed( py_seq ) ) );
//Now I actually creates the object from the Python tuple
bpl::object tmp = seq[0];
point->x = bpl::extract< int >( tmp );
@@ -87,6 +140,7 @@
point->y = bpl::extract< int >( tmp );
tmp = seq[2];
point->z = bpl::extract< int >( tmp );
+
}
};
@@ -94,7 +148,7 @@
void register_conversion(){
bpl::to_python_converter< point3d_t, to_tuple>();
-
+
bpl::converter::registry::push_back( &from_tuple::convertible
, &from_tuple::construct
, bpl::type_id<point3d_t>() );
@@ -102,13 +156,19 @@
}//namespace point3d_conversion
-point3d_t zero_point() {
- return point3d_t();
-}
-
-
BOOST_PYTHON_MODULE( auto_conversion ){
point3d_conversion::register_conversion();
- bpl::def("zero_point", &::zero_point);
+ bpl::def("point_ret_val_000", &::point_ret_val_000);
+ bpl::def("point_ret_val_101", &::point_ret_val_101);
+ bpl::def("point_ret_ref_010"
+ , &::point_ret_ref_010
+ , bpl::return_value_policy<bpl:: copy_non_const_reference>() );
+ bpl::def( "point_ret_ptr_110"
+ , &::point_ret_ptr_110
+ , bpl::return_value_policy<bpl::return_by_value>() );
+ bpl::def("test_point_val_000", &::test_point_val_000);
+ bpl::def("test_point_cref_010", &::test_point_cref_010);
+ bpl::def("test_point_ref_110", &::test_point_ref_110);
+ bpl::def("test_point_ptr_101", &::test_point_ptr_101);
}
Modified: pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/test.py
===================================================================
--- pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/test.py 2007-01-09 09:29:03 UTC (rev 862)
+++ pyplusplus_dev/docs/troubleshooting_guide/automatic_conversion/test.py 2007-01-09 21:24:49 UTC (rev 863)
@@ -1,26 +1,23 @@
import unittest
-import shared_ptr
+from auto_conversion import *
-
-class tester_t( unittest.TestCase ):
+class auto_conversion_tester_t( unittest.TestCase ):
def __init__( self, *args ):
unittest.TestCase.__init__( self, *args )
def test( self ):
- ptr = shared_ptr.create_ptr()
- self.failUnless( ptr.text == "ptr" )
- self.failUnless( shared_ptr.read_ptr( ptr ) == "ptr" )
+ self.failUnless( (0,0,0) == point_ret_val_000() )
+ self.failUnless( (1,0,1) == point_ret_val_101() )
+ self.failUnless( (0,1,0) == point_ret_ref_010() )
+ self.failUnlessRaises( TypeError, point_ret_ptr_110 )
+ self.failUnless( test_point_val_000( (0,0,0) ) )
+ self.failUnless( test_point_cref_010( (0,1,0) ) )
+ self.failUnlessRaises( TypeError, test_point_ref_110, (1,1,0) )
+ self.failUnlessRaises( TypeError, test_point_ptr_101, (1,0,1) )
- const_ptr = shared_ptr.create_const_ptr()
- self.failUnless( const_ptr.text == "const ptr" )
- self.failUnless( shared_ptr.read_const_ptr( const_ptr ) == "const ptr" )
-
- #testing conversion functionality
- self.failUnless( shared_ptr.read_const_ptr( ptr ) == "ptr" )
-
def create_suite():
suite = unittest.TestSuite()
- suite.addTest( unittest.makeSuite(tester_t))
+ suite.addTest( unittest.makeSuite(auto_conversion_tester_t))
return suite
def run_suite():
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|