如何使用 PyObjects 声明 Boost.Python C++ 类

Posted

技术标签:

【中文标题】如何使用 PyObjects 声明 Boost.Python C++ 类【英文标题】:How can i declare a Boost.Python C++ Class with PyObjects 【发布时间】:2014-05-21 13:17:51 【问题描述】:

我想用 PyObjects 编写一个 c++ 类,以便从 Python 访问它们,以便用现有的 Python 对象实例引用它们。简而言之,我想在 C++ 类中存储/管理 Python 对象实例。

例如:

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)
    ;

如果可以使用 Boost.Python,我想在 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

非常感谢您!

问候

弗洛

【问题讨论】:

【参考方案1】:

使用 Boost.Python 在 C++ 中管理 Python 对象时,应该考虑使用 boost::python::object 类而不是 PyObjectobject 的行为非常类似于 Python 变量,允许在 C++ 中编写类似 Python 的代码。此外,它们的行为类似于智能指针,提供引用计数和生命周期管理,因为需要使用 PyObject 显式管理引用计数。


这是一个基于原始代码的完整示例,演示使用boost::python::objectPyObject

#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)
    ;

互动使用:

>>> 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))

【讨论】:

谢谢你的榜样!!但我认为你在 BOOST_PYTHON_MODULE 中声明了一个 python 类,但我想要一个仅带有 PythonObjects 的 c++ 类。如果我想访问它们,我想将一些 python 对象实例外包给更快的 c++ 类以获得更好的性能

以上是关于如何使用 PyObjects 声明 Boost.Python C++ 类的主要内容,如果未能解决你的问题,请参考以下文章

我应该对这个块中的任何 PyObjects 使用 Py_INCREF 吗?我也正确 Py_DECREFing 我的对象吗?

C++使用boost.python编写Python扩展

Boost Python官方样例

来自python字符串的C char数组

从python字符串中提取的C字符数组

HTML变量如何声明并使用