question about handling pointers in C extensions

Harald Kirsch kirschh at lionbioscience.com
Wed Jul 25 09:47:39 CEST 2001


"Russell E. Owen" <owen at astrono.junkwashington.emu> writes:

> I would like a bit of help with handling pointers in C extensions. I 
> hope this is a simple question.
> 
> I want to write a Python interface to a device driver library. One 
> starts by opening the device and getting a particular kind of pointer, 
> e.g. (simplified):
>   DevType *dev_open()
> 
> Is the following reasonable, or is there a better way to do this?
> 
> static PyObject *open (PyObject *self, PyObject *args)
> ) {
>     PyObject *py_dev_p;
>     DevType *dev_p;
>     
>     /* call the C routine to open the device */
>     dev_p = dev_open();
>     if (dev_p == NULL) {
>         PyErr_SetString(PyExc_RuntimeError, "open failed");
>         return NULL;
>     }
> 
>     /* convert device pointer to a Python Long object */
>     py_dev_p = PyLong_FromVoidPtr ((void *) dev_p);

This makes py_dev_p into a reference you own, therefore ...

>     if (py_dev_p == NULL) {
>         return NULL;
>     }
> 
>     /* increment reference and return the PyLong */
>     Py_INCREF (py_dev_p);
>     return Py_BuildValue("O", py_dev_p);

... neither INCREF nor BuildValue are needed.

> }

In the long run you want to define your own PyObject type in which you
store the DevType *dev_p. The cast to long is a bit of a
hack. Something like

  typedef struct {
    PyObject_HEAD;
    DevType *dev_p;
  } DeviceObject;

You then want a related PyTypeObject along the lines of 

  PyTypeObject deviceTypeObject = {
    PyObject_HEAD_INIT(NULL);
    0,
    "Device",
    sizeof(DeviceObject),
    0,
    /**** more things to come, your book should have an example.
  };

Don't forget in your init code to

  deviceTypeObject.ob_type = &PyType_Type;

I found it like this in the docs, I think.

Having your own type of objects makes things a bit saver, because you
now can write:

static PyObject*
close (PyObject *obself, PyObject *args)
{
  DeviceObject *self;

  if( !obself ) {
    /* this was called as a module function like
       device.close(arg)
      where 'device' is the name of your module
    */
    if( !PyArg_ParseTuple(args, "O!", &deviceTypeObject, &self) ) 
      return NULL;
  } else {
    /* this was called like
       fin = device.open()
       fin.close()
       so we are sure already that obself is of the correct type
    */
    self = (DeviceObject*)obself;
  }

  /* Now do it */
  whateverCloseFunctionIsNecessary(self->dev_p);

  Py_INCREF(Py_None);
  return Py_None;
}


  Harald Kirsch


-- 
----------------+------------------------------------------------------
Harald Kirsch   | kirschh at lionbioscience.com | "How old is the epsilon?"
LION bioscience | +49 6221 4038 172          |        -- Paul Erdös
       *** Please do not send me copies of your posts. ***



More information about the Python-list mailing list