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
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to