Writing the Python Wrapper

The C structures and functions that we wrap in Pyrex behave like C structures and functions, not like Python objects and methods. Therefor we write wrappers for the C functions so they behave normally.

C
U
P
S

Function Wrappers

The last part of out CUPS module that we have to write is a wrapper for the cupsGetDests function. We start it in the same way we would start any Python procedure.

def get_dests():

Next we declare all the local C-variables. The first is the return value for call to cupsGetDests, which is going to supply an array of cups_dest_t structures. The second is a variable that we are going to use in the for-loop below.

    cdef cups_dest_t *dests
    cdef cups_dest_t currDest

Now we make the call to the C function cupsGetDests.

    numDests = cupsGetDests(&dests)

Notice that numDests was not declared because it was a normal Python integer.

The final job of our Python procedure is to unpack the C array and put the names into a Python list.

    retval = []
    for i in range(numDests):
        currDest = dests[i]
        retval.append(currDest.name)
    return retval

The loop starts by unpacking each element of the array dests into a local variable. Next, the name element of the cups_dest_t structure is appended to a list, before the list of names is returned.

X
O
S
D

Writing a Class

There are three parts to a Pyrex extension-class:

C-Variable Declaration

Writing a Python class to wrap a C structure begins by declaring the local variables. The variable declarations are the same for classes as they are for functions. For the XOSD wrapper-class we declare the local variable xosdWin immediately after the class declaration, as follows.

cdef class XOSD:
    cdef xosd *xosdWin

Note: You cannot declare the C variables inside the constructor (__new__).

The Constructor and Destructor Methods

The constructor has to be written next. Use the __new__ method to create the constructor — instead of using the traditional __init__ — as __new__ is called before the object is created. Initialise all the C variables, and libraries inside the constructor; for XOSD, the xosd_init function is called.

    def __new__(self, font, colour, timeout, pos):
        self.xosdWin = xosd_init(font, colour, timeout, pos,
                                 0, 1)

To wrap the destructor, override the __dealloc__ method. The xosd_uninit function is called inside the destructor to remove the XOSD window.

    def __dealloc__(self):
        xosd_uninit(self.xosdWin)

Alert readers would have noticed that the function xosd_uninit was not declared earlier. The declaration is left as an exercise to the reader.

Standard Methods

The final task is to write the standard methods that will be called by code outside the module. These methods are written in a similar way to standard Python functions. For our example, we will wrap up the xosd_display function, creating a display_text method that will display the text on the screen.

    def display_text(self, text):

Recall how xosd_display took a variable number of arguments. Because of this we have to convert text to the correct C-type ourselves, otherwise Pyrex would not know what type to make text. To do this we create a temporary C-variable, cText, that is passed to xosd_display.

        cdef char *cText
        cText = text
        xosd_display(self.xosdWin, 1, XOSD_string, cText)
Previous Contents Next

Michael JasonSmith
Last modified: Mon Jun 24 11:55:54 NZST 2002