Jump to content
  • Advertisement
Sign in to follow this  

[Py++] Automatically register boost::shared_ptr to python

This topic is 3171 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I would like Py++ to automatically insert "boost::pytheon::register_ptr_to_python< boost::shared_ptr<T> >()" for all classes that it exposes. I want this, because I heavily rely on boost::shared_ptr in my project and I want to be able to convert those to boost::python::object in order to pass them to the python interpreter. Contrary to my expectation, this has proven a bit complicated. Ultimately, I came up with something that works, but I'm wondering why there isn't an easier way of doing it. Here's what I do at the moment:
# Register Smart Pointers
find_classes = code_creators.creator_finder.find_by_class_instance
class_creators = find_classes(what=code_creators.class_t, where=mb.code_creator, recursive=True)
for creator in class_creators:
Do you see any problems with this? Has anyone tried something like this before?

Share this post

Link to post
Share on other sites
Well, I can answer my first question myself. I found one problem, the previous code can create duplicate "bp::register_ptr_to_python< boost::shared_ptr<T> >()" statements for certain classes. (For example if Py++ sees a class having a boost::shared_ptr<T> as a member...)

Here's a version that fixes the problem. This is a complete Py++ module builder script to provide some context:

#! /usr/bin/python

import os
import sys
sys.path.append( '../../../..' )
from pyplusplus import module_builder
from pyplusplus import code_creators

mb = module_builder.module_builder_t(

#Now it is the time to give a name to our module
mb.build_code_creator( module_name='classes' )

#Register Smart Pointers
find_classes = code_creators.creator_finder.find_by_class_instance
class_creators = find_classes(what=code_creators.class_t, where=mb.code_creator, recursive=True)
smart_pointer_registrators = find_classes(what=code_creators.smart_pointer_registrator_t, where=mb.code_creator, recursive=True)
for creator in [creator for creator in class_creators if creator not in [registrator.class_creator for registrator in smart_pointer_registrators]]:

#And finally we can write code to the disk
mb.write_module( os.path.join( os.path.abspath('.'), 'classes.inl' ) )

And here are the sources I used for testing:

#pragma once
#ifndef CLASSES_H
#define CLASSES_H

#if defined(__GCCXML__)
#define _HAS_TR1 0

#include <iostream>

#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>

class Class1
typedef boost::shared_ptr<Class1> ptr;

int x;
int y;

Class1(int _x, int _y):x(_x),y(_y){}

class Class2
typedef boost::shared_ptr<Class2> ptr;

Class1::ptr c;

Class2(const Class1::ptr& _c):c(_c){}

virtual void f(){ std::cout << "Class2()" << std::endl; }


classes.inl (generated)
// This file has been generated by Py++.

#include "boost/python.hpp"

#include "classes.h"

namespace bp = boost::python;

struct Class2_wrapper : Class2, bp::wrapper< Class2 > {

Class2_wrapper(Class2 const & arg )
: Class2( arg )
, bp::wrapper< Class2 >(){
// copy constructor


Class2_wrapper(::boost::shared_ptr< Class1 > const & _c )
: Class2( _c )
, bp::wrapper< Class2 >(){
// constructor


virtual void f( ) {
if( bp::override func_f = this->get_override( "f" ) )
func_f( );
this->Class2::f( );

void default_f( ) {
Class2::f( );


{ //::Class1
typedef bp::class_< Class1 > Class1_exposer_t;
Class1_exposer_t Class1_exposer = Class1_exposer_t( "Class1", bp::init< int, int >(( bp::arg("_x"), bp::arg("_y") )) );
bp::scope Class1_scope( Class1_exposer );
Class1_exposer.def_readwrite( "x", &Class1::x );
Class1_exposer.def_readwrite( "y", &Class1::y );
bp::register_ptr_to_python< boost::shared_ptr< Class1 > >(); //All that trouble just to get this!

{ //::Class2
typedef bp::class_< Class2_wrapper > Class2_exposer_t;
Class2_exposer_t Class2_exposer = Class2_exposer_t( "Class2", bp::init< boost::shared_ptr< Class1 > const & >(( bp::arg("_c") )) );
bp::scope Class2_scope( Class2_exposer );
bp::implicitly_convertible< boost::shared_ptr< Class1 > const &, Class2 >();
{ //::Class2::f

typedef void ( ::Class2::*f_function_type )( ) ;
typedef void ( Class2_wrapper::*default_f_function_type )( ) ;

, f_function_type(&::Class2::f)
, default_f_function_type(&Class2_wrapper::default_f) );

Class2_exposer.def_readwrite( "c", &Class2::c );
bp::register_ptr_to_python< boost::shared_ptr< Class2 > >(); //All that trouble just to get this!

#include "classes.inl"

namespace py = boost::python;

int main(int argc, char **argv)
int exit = EXIT_SUCCESS;



Class1::ptr o1 = boost::make_shared<Class1>(1,2);

py::object main_module = py::import("__main__");
py::object main_namespace = main_module.attr("__dict__");

py::object po1(o1);
main_namespace["o1"] = po1;

py::object ignored = py::exec(
"from classes import *\n"
"class Class3(Class2):\n"
" def __init__(self,c):\n"
" Class2.__init__(self,c)\n"
" def f(self):\n"
" print \"Class3()\"\n"
"o3 = Class3(o1)\n",
main_namespace, main_namespace

boost::shared_ptr<Class2> o3 = py::extract< boost::shared_ptr<Class2> >(main_namespace["o3"]);

std::cout << "Class1("<< py::extract<int>(po1.attr("x")) << "," << py::extract<int>(po1.attr("y")) << ")" << std::endl;

catch(const py::error_already_set&)


return exit;

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!