0

i want to write a c++ class with PyObjects to access them from Python to reference them with an existing Python object instance. In short words i want to store/manage Python object instances in the C++ class.

For example:

struct Var
{
    PyObject *Test_1;
    PyObject *Test_2;

};

#include <boost/python.hpp>
using namespace boost::python;

BOOST_PYTHON_MODULE(Var)
{
    class_<Var>("Var", init<std::string>())
        .def_readwrite("Test_1", &Var::value)
        .def_readwrite("Test_2", &Var::value)
    ;
}

in python i want to do this if it is possible with Boost.Python:

class Test:
    def __init__(self, a = 0, b = 2):
        self.a = 0
        self.b = 0


test = Test(2,2)

import Var
newStore = Var
newStore.Test_1 = test

Thank you a lot in advance !

greets

Flo

1 Answer 1

2

When managing Python objects in C++ with Boost.Python, one should consider using the boost::python::object class rather than PyObject. The object acts very much like a Python variables, allowing for Python-ish code in C++. Furthermore, they behave similar to a smart pointer, providing referencing counting and lifetime management, where as one would need to explicitly manage the reference count with a PyObject.


Here is a complete example based on the original code that demonstrates using boost::python::object and PyObject:

#include <boost/python.hpp>

/// @brief Mockup type that can manage two Python objects.
struct var
{
  boost::python::object test_1; // managed
  PyObject* test_2;             // must explicitly manage

  var()
    : test_2(Py_None)
  {
    Py_INCREF(test_2);
  }

  ~var()
  {
    Py_DECREF(test_2);
  }
};

/// @brief Auxiliary function used to return a non-borrowed reference to
//         self.test_2.  This is necessary because Boost.Python assumes
//         that PyObject* passed from C++ to Python are not borrowed.
PyObject* var_test_2_getter(const var& self)
{
  PyObject* object = self.test_2;
  Py_INCREF(object);
  return object;
}

/// @brief Auxiliary function used to manage the reference count of
///        objects assigned to var.test_2.
void var_test_2_setter(var& self, PyObject* object)
{
  Py_DECREF(self.test_2);
  self.test_2 = object;
  Py_INCREF(self.test_2);
}

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<var>("Var", python::init<>())
    .def_readwrite("Test_1", &var::test_1)
    .add_property("Test_2", &var_test_2_getter, &var_test_2_setter)
    ;
}

Interactive usage:

>>> class Test:
...     def __init__(self, a=0, b=2):
...         self.a = a
...         self.b = b
... 
>>> test = Test(2, 2)
>>> from sys import getrefcount
>>> count = getrefcount(test)
>>> import example
>>> store = example.Var()
>>> store.Test_1 = test
>>> assert(store.Test_1 is test)
>>> assert(count + 1 == getrefcount(test))
>>> assert(store.Test_1.a == 2)
>>> store.Test_1.a = 42
>>> assert(test.a == 42)
>>> store.Test_2 = test
>>> assert(store.Test_2 is test)
>>> assert(count + 2 == getrefcount(test))
>>> assert(count + 2 == getrefcount(store.Test_2))
>>> store.Test_2 = None
>>> assert(count + 1 == getrefcount(test))
>>> store = None
>>> assert(count == getrefcount(test))
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your example!! But i think you declared a python class in the BOOST_PYTHON_MODULE, but i want a c++ class only with PythonObjects.I want to outsource some python objectinstances to a faster c++ class for a better performance if i want o access to them

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.