如何从c++返回对动态类型的引用并在Python中保存它?

How do I return a reference to a dynamic type from C++ and hold it in Python?

本文关键字:Python 保存 引用 c++ 返回 类型 动态      更新时间:2023-10-16

我正在编写一些代码,根据列索引从一行返回列值。在c++中,行会不时更新,我希望python代码保留对列值的引用。下面的代码反映了我当前的解决方案,其中我必须反复获取列值。

struct Foo
{
   PyObject * get(int pos)
   {
       // Position 0 is an integer value.  Position 1 is a float value
       if (pos == 0)
           return Py_BuildValue ("i", m_int);
       else
           return Py_BuildValue ("f", m_float);
   }
   void set_int(int i)
   {
       m_int = i;
   }
   void set_float(float f)
   {
       m_float = f;
   }
   int m_int;
   float m_float;
};

我的绑定很简单:

class_<Foo> ("Foo")
        .def("get", &Foo::get)
        .def("set_int", &Foo::set_int)
        .def("set_float", &Foo::set_float)
        ;

这在python级别是这样工作的:

In [16]: foo = Foo()
In [17]: foo.set_int(1)
In [18]: foo.set_float(2.5)
In [19]: i = foo.get(0)
In [20]: f = foo.get(1)
In [21]: i
Out[21]: 1
In [22]: type(i)
Out[22]: int
In [23]: f
Out[23]: 2.5
In [24]: type(f)
Out[24]: float

到目前为止,一切顺利。但是,当我修改foo时,我希望I和f反映新的值。当前,它们反映的是旧值。

In [25]: foo.set_int(42)
In [26]: i
Out[26]: 1

我如何设置c++和绑定代码,使'get'返回一个引用,而不是Foo成员变量的副本?

您需要在对象类中包装整数值。在Python中,原语是不可变的,所以当你返回一个int值时,它永远不会引用原始int,只是一个const副本。可以返回如下形式的新结构体:

struct IntWrap {
     int *value;
     int get() { return *value; }
     void set_int(int nval) { *value = nval; }
     ...
};
class_<IntWrap > ("IntWrap")
     .def("get", &IntWrap::get)
     .set("set_int", &IntWrap::set_int)
     ...

并使包装器函数绑定将该结构体视为Python中的可变整数。然而,这确实违反了Python中原语的constness习惯用法。

这是一篇关于有效地继承strint的文章,在那里你可以对整数样式对象进行更改,以使用IntWrap代替(如果你想要的东西更像int开箱外)。