[C++-sig] const shared_ptr and py++ / boost.python
Nicolas Regnault
nicolas.regnault at lpnhe.in2p3.fr
Thu Jun 4 22:37:59 CEST 2009
Dear all:
I am wrapping a library which relies heavily on boost smart pointers
(mainly boost::shared_ptr< T >). In particular, many functions and methods
have signatures like:
void my_func( const boost::shared_ptr< MyClass > & );
Everything works well from within C++ programs. But I encounter a serious
problem with the wrappers I have generated with py++. Indeed, when passing
from python, something which wraps a "shared_ptr< MyClass >" to
my_function(), the code within the function apparently gets a shared_ptr
with a use_count equal to 1 (pointing to the same address), whatever the
use_count of the shared_ptr passed to the function.
I haven't been able to see what boost.python is doing in between, but
something gets altered. Any idea of what is wrong with the wrappers ?
Here is a small example:
////////////////////////////////////////////////////////////////////////
// -*- C++ -*- //
//tst.hpp
//
#ifndef TST_HPP
#define TST_HPP
#include <vector>
#include <boost/shared_ptr.hpp>
struct Foo
{
Foo() : count(0) {}
int count;
};
typedef std::vector< boost::shared_ptr< Foo > > FooVector;
void build_vector( boost::shared_ptr< Foo > &, FooVector & );
// print the shared_ptr<>::use_count
void print_use_count( boost::shared_ptr< Foo > & );
// print the shared_ptr<>::use_count
void print_use_count_const( const boost::shared_ptr< Foo > & );
#endif
////////////////////////////////////////////////////////////////////////
// -*- C++ -*-
//
// tst.cpp
//
#include <iostream>
#include <iomanip>
#include "tst.hpp"
using namespace std;
using namespace boost;
void build_vector( shared_ptr< Foo > & foo_ptr, FooVector & vec )
{
vec.clear();
for( unsigned int i=0; i<100; i++ )
{
vec.push_back( foo_ptr );
}
}
void print_use_count( shared_ptr< Foo > & ptr ) {
cout << "[print_use_count] use_count=" << ptr.use_count()
<< " addr=" << std::ios::hex << ptr.get()
<< endl;
}
void print_use_count_const( const shared_ptr< Foo > & ptr ) {
cout << "[print_use_count] use_count=" << ptr.use_count()
<< " addr=" << std::ios::hex << ptr.get()
<< endl;
}
////////////////////////////////////////////////////////////////////////
// -*- C++ -*-
//
// export_tst.cpp
//
#include "boost/shared_ptr.hpp"
#include "boost/python.hpp"
#include "boost/python/suite/indexing/vector_indexing_suite.hpp"
#include "tst.hpp"
namespace bp = boost::python;
BOOST_PYTHON_MODULE(_tst){
bp::class_< std::vector< boost::shared_ptr<Foo> > >("vector_Foo")
.def( bp::vector_indexing_suite< ::std::vector< boost::shared_ptr<Foo> >,
true >() );
{ //::Foo
typedef bp::class_< Foo, boost::shared_ptr< Foo > > Foo_exposer_t;
Foo_exposer_t Foo_exposer = Foo_exposer_t( "Foo" );
bp::scope Foo_scope( Foo_exposer );
Foo_exposer.def( bp::init< >() );
Foo_exposer.def_readwrite( "count", &Foo::count );
}
{ //::build_vector
typedef void ( *build_vector_function_type )( ::boost::shared_ptr< Foo >
&,::FooVector & );
bp::def(
"build_vector"
, build_vector_function_type( &::build_vector )
, ( bp::arg("arg0"), bp::arg("arg1") ) );
}
{ //::print_use_count
typedef void ( *print_use_count_function_type )( ::boost::shared_ptr< Foo >
& );
bp::def(
"print_use_count"
, print_use_count_function_type( &::print_use_count )
, ( bp::arg("arg0") ) );
}
{ //::print_use_count_const
typedef void ( *print_use_count_const_function_type )( ::boost::shared_ptr<
Foo > const & );
bp::def(
"print_use_count_const"
, print_use_count_const_function_type( &::print_use_count_const )
, ( bp::arg("arg0") ) );
}
}
////////////////////////////////////////////////////////////////////////
// -*- C++ -*-
//
// main.cpp
//
#include <vector>
#include <boost/shared_ptr.hpp> #include "tst.hpp"
using namespace boost;
int main()
{
shared_ptr< Foo > f( new Foo );
FooVector vec;
build_vector(f, vec);
print_use_count(f);
print_use_count_const(f);
}
########################################################################
#!/usr/bin/env python
import _tst
def main():
f = _tst.Foo()
vec = _tst.vector_Foo()
_tst.build_vector(f, vec)
_tst.print_use_count(f)
_tst.print_use_count_const(f)
if __name__ == "__main__":
main()
########################################################################
# Makefile
########################################################################
all: main _tst.so
%.os : %.cpp
g++ -c $< -o $@ -fPIC -I /usr/include/python2.5
libtst.so: tst.os
g++ -shared $< -o $@
main: main.os libtst.so
g++ $< -o $@ -L . -ltst
_tst.so: export_tst.os libtst.so
g++ -shared $< -o $@ -lboost_python -L . -ltst
########################################################################
$ ./main
[print_use_count] use_count=101 addr=80x1617010
[print_use_count] use_count=101 addr=80x1617010
$ ./main.py
[print_use_count] use_count=101 addr=80x121b2b0
[print_use_count] use_count=1 addr=80x121b2b0
Nicolas.
--
Nicolas Regnault Laboratoire de Physique Nucléaire et de Hautes Energies
4, place Jussieu - Tour 43 RdC - 75252 Paris Cedex 05 +33 1 44 27 73 29
More information about the Cplusplus-sig
mailing list