[C++-sig] Lifetime of Python object for a pointer argument

David Abrahams david.abrahams at rcn.com
Sat Feb 16 17:41:20 CET 2002


Your analysis of what's going wrong here is correct. There is a way to make
what you're doing "work" with Boost.Python V1, but it's ugly. You have to
wrap geometry with a "callback" class as though it had virtual
functions(www.boost.org/libs/python/doc/overriding.html):

// Warning: off-the-cuff, untested

struct geometry_callback : geometry
{
    geometry(PyObject* self, PyObject* grid_obj)
        : grid_obj(grid_obj)
    { Py_XINCREF(grid_obj); }

    ~geometry() { Py_XDECREF(grid_obj); }

    PyObject* grid_obj;
};

python::class_builder<geometry, geometry_callback>
geometry_class(this_module, "geometry");
...

but note, that your to_python(const grid*) function also results in the grid
being /copied/ (probably not what you want). Boost.Python V2 (currently in
prerelease) provides a better approach:

BOOST_PYTHON_MODULE_INIT(ngf2)
{
   python::module("ngf2)
      .add(
           class<grid>("grid")
               .def_init()
          )
      .add(
           class<geometry>("geometry")

              .def_init(args<const grid*>()
              // Keep the grid alive as long as the geometry is.
                        , python::with_custodian_and_ward<1,2>())

              .def("getGrid", &geometry::getGrid
              // keep the geometry object alive as long as the result is
                   , python::return_internal_reference<>())
          );
}

----- Original Message -----
From: "Min Xu" <minxu at sci.ccny.cuny.edu>
> Hi,
>
> I am a newbie of boost python. In the process of converting a SWIG
> wrapping of a C++ library to boost python, I encounter the following
> problem:
>
> // C++ part
> class grid
> {
> public:
>    grid() { ... }
>    ...
> };
>
> class geometry
>

> public:
>     geometry(const grid * gd) : gd(gd) {}
>     const grid* getGrid() const { return gd; }
> private:
>     const grid* gd;
> };
>
> // Wrapper
> #include <boost/python/class_builder.hpp>
> namespace python = boost::python;
>
> PyObject* to_python(const grid* g) {
>      return to_python(*g); // convert const grid* in terms of const
> grid&
> }
>
> BOOST_PYTHON_MODULE_INIT(ngf2)
> {
>   try
>   {
>     python::module_builder this_module("ngf2");
>     python::class_builder<grid> grid_class(this_module, "grid");
>     grid_class.def(python::constructor<>());
>     python::class_builder<geometry> geometry_class(this_module,
> "geometry");
>     geometry_class.def(python::constructor<const grid*>());
>   }
>   ...
> }
>
> The compilation works well (the newest CVS version of boost python).
> In python:
> >>> from ngf2 import *
> >>> a=geometry (grid())
> >>> a.getGrid ().a()
> 8.6723632812500586   # corrupted as grid() is deleted automatically?
> >>> g=grid()
> >>> b=geometry (g)
> >>> b.getGrid ().a()
> 1.0                  # expected.
> >>> del g
> >>> b.getGrid ().a()
> 1.3285421879284814e-269 # corrupted
>
> I understand it may be a ref counting problem. Is there any way to make
> the first idiom work?
>
> Thanks!
>
>
> Min Xu
>
>
>
>
>
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
>





More information about the Cplusplus-sig mailing list