2015-06-22 28 views
1

的属性,它编译正确添加新的Python类型:类型错误:无法设置下面的python-C代码内置/扩展型

#include <Python.h> 
#include <structmember.h> 

struct rangerr { 
     long min; 
     long max; 
}; 

//Python type to represent rangerr 
struct py_rangerr { 
    PyObject_HEAD 
    struct rangerr range; 
}; 
// * get & set methods for py_rangerr 

static PyObject * py_rangerr_min_get(struct py_rangerr *self) { 
    self->range.min = 1; 
     return PyLong_FromLong(self->range.min); 
} 
static PyObject * py_rangerr_min_set(struct py_rangerr *self) { 
printf("Setter called"); 
self->range.min = 1; 
} 


static PyObject * py_rangerr_max_get(struct py_rangerr *self) { 
    self->range.max = 10; 
     return PyLong_FromLong(self->range.max); 
} 


//* GetSet method definition for py_rangerr 
static PyGetSetDef py_rangerr_getset[] = { 
    {"min",(getter)py_rangerr_min_get, (setter)py_rangerr_min_set, "min",NULL}, 
    {"max",(getter)py_rangerr_max_get, NULL, "max",NULL}, 

    /* Sentinel */ 
    {NULL}, 
}; 

/****************************************************************************** 
*/ 
static void py_rangerr_dealloc(struct py_rangerr *self) { 
     self->ob_type->tp_free((PyObject *)self);    
} 

static PyTypeObject py_rangerr_type = { 
    PyObject_HEAD_INIT(NULL)  
    .tp_name  = "rangerr",   
    .tp_basicsize = sizeof(struct py_rangerr), 
    .tp_dealloc = (destructor) py_rangerr_dealloc, 
    .tp_flags  = Py_TPFLAGS_DEFAULT,       
    .tp_alloc  = PyType_GenericAlloc,      
    .tp_doc  = "rangerr",         
    .tp_getset = py_rangerr_getset,     
}; 

void 
initrangerr(void) 
{ 
    PyObject* mod; 

mod = Py_InitModule3("rangerr", NULL, "An extension with a type."); 
    if (mod == NULL) { 
     return; 
    } 
    py_rangerr_type.tp_new = PyType_GenericNew; 
    if (PyType_Ready(&py_rangerr_type) < 0){ 
     return; 
    } 


Py_INCREF(&py_rangerr_type); 
    PyModule_AddObject(mod, "rangerr", (PyObject*)&py_rangerr_type); 

} 

但是当我尝试调用的set/get方法,它抛出以下错误:

>>> import rangerr as r 
>>> r.rangerr.min 
<attribute 'min' of 'rangerr' objects> 
>>> r.rangerr.min=2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't set attributes of built-in/extension type 'rangerr' 
>>> type(r.rangerr.min) 
<type 'getset_descriptor'> 

是否需要添加类似“PyMemberDef”的内容?感谢任何指点或帮助。

+2

你似乎在试图改变类定义的值,而不是一个实例。是想要的行为 – Julius

+0

我只是想看看是否(一)在定义中设置一个默认值并获取它或(b)通过实例一设置它们的工作。到目前为止,我无法让他们两个都工作。 –

回答

1

它不是直接可能有一个参数的默认值。你可以添加一个函数到你的模块来设置全局默认值为静态变量。

如果只想初始化您的实例,你应该定义PyTypeObject.tp_init

static int py_rangerr_init(struct py_rangerr *self, PyObject *args, PyObject *kwds) { 
    static char *kwlist[] = {"min", "max", NULL}; 
    int min = 0, max = 1; 

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &min, &max)) 
     return -1; 

    self->range.min = min; 
    self->range.max = max; 

    return 0; 
} 

static PyTypeObject py_rangerr_type = { 
    PyObject_HEAD_INIT(NULL) 
    [...] 
    .tp_init  = (initproc) py_rangerr_init, 
}; 

如果你不给minmax值,从线int min = 0, max = 1;默认值将被使用。

关于您关于PyMemberDef使用,它是,对于类型,如int它可能是少重复不易出错使用PyTypeObject.tp_members,而不是PyTypeObject.tp_getset问题。

除了二传手的类型定义为:

typedef int (*setter)(PyObject *, PyObject *, void *); 
+0

感谢您的回复,tynn :)今天晚些时候会试一试。 OT:顺便说一句,你对C-Python文档/链接/书有任何建议吗?除了nedbatchelder.com&docs.python.org文档。 –

+1

不是。只有docs.python.org。但是Python的源代码有很多帮助。 – tynn

+0

好的,非常感谢。 –

相关问题