如何在自定义嵌入式Python对象中存储指针
根据教程,我已经在C中创建了一个自定义Python类型。在我的C语言中,我收到一个指向结构的指针,我希望能够从Python中获取并设置结构中的值,而无需复制它。即如何在自定义嵌入式Python对象中存储指针,python,c,python-2.7,pointers,Python,C,Python 2.7,Pointers,根据教程,我已经在C中创建了一个自定义Python类型。在我的C语言中,我收到一个指向结构的指针,我希望能够从Python中获取并设置结构中的值,而无需复制它。即 a = myObject.x() # gets the x value in the struct. 或 但是,我看不到如何在python对象中存储指针 我当前的对象定义目前只是python网站上的基本对象实现 typedef struct { PyObject_HEAD myStruct *s; } KeyObje
a = myObject.x() # gets the x value in the struct.
或
但是,我看不到如何在python对象中存储指针
我当前的对象定义目前只是python网站上的基本对象实现
typedef struct {
PyObject_HEAD
myStruct *s;
} KeyObject;
static PyTypeObject KeyType = {
PyVarObject_HEAD_INIT(NULL, 0)
"ckb.Key", /* tp_name */
sizeof(KeyObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"Key objects", /* tp_doc */
};
static PyMethodDef key_methods[] = {
{NULL} /* Sentinel */
};
下面是一个示例(cbk.c),它可以作为此任务的主干:
#包括“external.h”
#包括“Python.h”
#定义模块名称“ckb”
#定义密钥\u类\u名称“密钥”
/*
typedef结构InnerStruct_标记{
int x;
}内部结构;
//*/
typedef结构KeyObject_标记{
皮尤头
InnerStruct*内部;
}键对象;
静态PyObject*键\u新建(PyTypeObject*类型、PyObject*参数、PyObject*kwds){
关键对象*自我;
self=(KeyObject*)类型->tp_alloc(类型,0);
if(self!=NULL){
//self->inner=(InnerStruct*)calloc(1,sizeof(Key));
self->internal=getExternalPtr(1234);//不要在这里分配,从外部库获取指针
如果(自->内部==NULL){
Py_DECREF(self);
返回NULL;
}
}
返回(PyObject*)self;
}
静态无效键\u解除锁定(键对象*自身){
//自由(自我->内部);
delExternalPtr(self->internal);//使用外部dellocation函数(可选)
Py_类型(self)->tp_-free((PyObject*)self);
}
静态PyObject*Key_getX(KeyObject*self,void*closure){
从long(self->inner->x)返回PyInt_;
}
静态int Key_setX(KeyObject*self,PyObject*value,void*closure){
如果(值==NULL){
PyErr_SetString(PyExc_TypeError,“无法删除“x”);
返回-1;
}
如果(!PyInt_检查(值)){
PyErr_SetString(PyExc_TypeError,“'x'值必须是int”);
返回-1;
}
self->inner->x=((PyIntObject*)值)->ob;
返回0;
}
静态PyGetSetDef密钥\u getsets[]={
{“x”,(getter)Key_getX,(setter)Key_setX,“x”,NULL},
{NULL}//Sentinel
};
静态PyTypeObject键类型={
PyVarObject\u HEAD\u INIT(NULL,0)
MOD_NAME“.”KEY_CLASS_NAME,/*tp_NAME*/
sizeof(KeyObject),/*tp_basicsize*/
0,/*tp\u itemsize*/
(析构函数)键_dealloc,/*tp_dealloc*/
0,/*tp_打印*/
0,/*tp\u getattr*/
0,/*tp_setattr*/
0,/*tp\u比较*/
0,/*tp_repr*/
0,/*tp\U作为\U编号*/
0,/*tp\u作为\u序列*/
0,/*tp_作为映射*/
0,/*tp_散列*/
0,/*tp\u调用*/
0,/*tp_str*/
0,/*tp_getattro*/
0,/*tp_setattro*/
0,/*tp作为缓冲区*/
Py_TPFLAGS_默认值|
Py_TPFLAGS_BASETYPE,/*tp_flags*/
键类名称“对象”/*tp\U文档*/
0,/*tp\u导线测量*/
0,/*tp_清除*/
0,/*tp_*/
0,/*tp_弱偏移*/
0,/*tp_iter*/
0,/*tp_iternext*/
0,/*tp_方法*/
0,/*tp_成员*/
Key\u getset,/*tp\u getset*/
0,/*tp_基*/
0,/*tp_dict*/
0,/*tp\u descr\u get*/
0,/*tp\u descr\u集*/
0,/*tp\u偏移量*/
0,/*tp_init*/
0,/*tp_alloc*/
键为新,/*tp键为新*/
};
#定义键检查精确(op)((op)->ob_类型==&键检查类型)
静态PyMethodDef模块_方法[]={
{NULL}//Sentinel
};
PyMODINIT_FUNC initckb(无效){
PyObject*m;
if(PyType\u Ready(&Key\u Type)<0)
返回;
m=Py_InitModule3(MOD_名称、module_方法、,
MOD_NAME”:创建扩展类型(“KEY_CLASS_NAME”)的示例模块;
Py_增量(&键类型);
PyModule_AddObject(m,键类名称,(PyObject*)和键类型);
}
注释:
- 为清晰起见,已重命名(重新组织)现有结构名称/成员
- 内部结构只有一个构件(x),这足以说明问题
- 一切都依赖于页面上的(问题中也提到了这一点)
- 由于包装器对象(键)包含指针(内部),为了避免每次访问它们时都检查它们是否为NULL:
- 添加了一个初始化它们的构造函数(Key_new-相当于Python中的u new)
- 还添加了一个析构函数(Key_dealloc-Python中等效的_del__)-它的作用正好相反-以避免内存泄漏(这只是前面的一个项目符号结果)
- 通过Key_getX、Key_setX函数访问InnerStruct的x成员(注意它们在Key_getset中引用):
- 来自Python的内部x成员将由key_instance.x访问,因为它是一个key instance属性
- 这种方法比使用getter(get_x())和setter(set_x(value))更有意义,而且更像python
- 但是,如果首选getter/setter方式,则应该稍微修改Key_getX、Key_setX签名(我认为删除最后一个参数就可以了),并且它们应该在Key_方法中引用-这应该指定给KeyType作为tp_方法(也在上面的网页中描述)
- 在向InnerStruct添加新成员时,只需要复制和调整为x完成的内容(当然,如果有些函数看起来太相似的话)
typedef struct { PyObject_HEAD myStruct *s; } KeyObject; static PyTypeObject KeyType = { PyVarObject_HEAD_INIT(NULL, 0) "ckb.Key", /* tp_name */ sizeof(KeyObject), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ "Key objects", /* tp_doc */ }; static PyMethodDef key_methods[] = { {NULL} /* Sentinel */ };
- 来自Python的内部x成员将由key_instance.x访问,因为它是一个key instance属性