1

Below python-c code which compiles properly

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

}

but when I try to invoke set/get method It throws below errors:

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

Do I need add something like "PyMemberDef" ? Thanks for any pointers or help.

2
  • 2
    You seem to be trying to change the value in the class definition, not in an instance. is that the desired behavior Commented Jun 22, 2015 at 17:06
  • I'm just trying to see whether either (a) setting a default value in the definition and fetching it or (b) set it via instance one them works. So far I'm unable to get both of them working. Commented Jun 22, 2015 at 17:23

1 Answer 1

2

It's not directly possible to have a default value for arguments. You could add a function to your module to set global default values as static variables.

If you only want to initialize your instance, you should define PyTypeObject.tp_init like

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,
};

If you don't give values for min or max, the default values from the line int min = 0, max = 1; will be used.

In relation to your question about the usage of PyMemberDef, it is, that for types like int it might be and less repetitive less error-prone to use PyTypeObject.tp_members instead of PyTypeObject.tp_getset.

Besides the typedef of setter is:

typedef int (*setter)(PyObject *, PyObject *, void *);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the response, tynn :) Will give it a try later today. OT: btw, do you have any suggestions for C-Python documents/links/books? Other than nedbatchelder.com & docs.python.org docs.
Nope. Only docs.python.org. But the python source code helps a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.