我为我的 Box 类中的公共变量 number_bananas 创建了getsetter。 number_bananas 是公开的,因为盒子已解锁,任何人都可以吃香蕉或在盒子中放更多东西。
这是我的PyBox类型:
typedef struct
{
PyObject_HEAD
Box *bx;
} PyBox;
在Box类中,我定义了:
class Box {
public:
Box(double l, double b, double h);
int number_bananas;
...
Box::Box(double l, double b, double h)
{
number_bananas = 11;
length = l;
breadth = b;
height = h;
}
这是我定义的get / setter:
static PyObject *pyBox_getBananas(PyBox *self, void *closure)
{
Py_INCREF(self->bx->number_bananas);
return self->bx->number_bananas;
}
static int pyBox_setBananas(PyBox *self, PyObject *value, void *closure)
{
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "You're trying to put something that is not a banana!!");
return -1;
}
Py_DECREF(self->bx->number_bananas);
Py_INCREF(value);
self->bx->number_bananas = value;
return 0;
}
static PyGetSetDef pyBox_getseters[] = {
{"number_bananas", (getter)pyBox_getBananas, (setter)pyBox_setBananas, "number of bananas", NULL},
{NULL}
};
我用来实例化Box类的构造函数由以下方式定义:
static int pyBox_init(PyObject *self, PyObject *args, PyObject *kwds)
{
static char* nams[] = {"length","breadth","height", NULL};
int l, b, h;
if(!PyArg_ParseTupleAndKeywords(args, kwds, "iii", nams, &l, &b, &h))
return -1;
((PyBox *)self)->bx = &(Box::Box(l,b,h));
return 0;
}
static PyObject *pyBox_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyBox *self;
self = (PyBox *) type->tp_alloc(type, 0);
return (PyObject *)self;
}
模块编译成功。但是,我找不到如何从Python访问属性 number_bananas 。
以下结果将导致致命错误(段错误):
import adventureIsland
bo = adventureIsland.box(1,1,1)
print(bo.number_bananas)
所以...我的问题是如何从Python访问/设置 number_bananas ?
谢谢!
答案 0 :(得分:1)
self->bx->number_bananas
不是PyObject*
,因此不能增加或减少。相反,您想将其与PyObject*
之间进行转换。在Python3中,您可以使用various PyLong_*
functions进行此操作。
一些未经测试的代码是:
static PyObject *pyBox_getBananas(PyBox *self, void *closure)
{
return PyLong_FromLong(self->bx->number_bananas);
}
static int pyBox_setBananas(PyBox *self, PyObject *value, void *closure)
{
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "You're trying delete the attribute!!");
return -1;
}
int valuei = PyLong_AsLong(value);
if (valuei==-1 and PyErr_Occurrred()) {
return -1;
}
self->bx->number_bananas = valuei;
return 0;
}
如果int
(number_of_bananas
)和long
(PyLong_AsLong
的结果)的大小不同,则可能存在太大的数字问题。可能值得您尝试识别并引发异常。
由于构造函数问题,您还有其他问题:
((PyBox *)self)->bx = &(Box::Box(l,b,h));
这会将bx
设置为指向临时Box
,该临时{几乎立即在创建后就停止存在。您应该做的是使用Box
运算符在堆上分配new
。 (现在发生的事情是,您指向的内存正在其他功能中重用,因此“值”以令人困惑的方式发生了变化。)
((PyBox *)self)->bx = new Box::Box(l,b,h);
然后,请确保在析构函数中delete
(以避免内存泄漏)。