Python Language ctypes Complex usage


Let's combine all of the examples above into one complex scenario: using libc's lfind function.

For more details about the function, read the man page. I urge you to read it before going on.

First, we'll define the proper prototypes:

>>> compar_proto = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
>>> lfind_proto = CFUNCTYPE(c_void_p, c_void_p, c_void_p, POINTER(c_uint), c_uint, compar_proto)

Then, let's create the variables:

>>> key = c_int(12)
>>> arr = (c_int * 16)(*range(16))
>>> nmemb = c_uint(16)

And now we define the comparison function:

>>> def compar(x, y):
        return x.contents.value - y.contents.value

Notice that x, and y are POINTER(c_int), so we need to dereference them and take their values in order to actually compare the value stored in the memory.

Now we can combine everything together:

>>> lfind = lfind_proto(libc.lfind)
>>> ptr = lfind(byref(key), byref(arr), byref(nmemb), sizeof(c_int), compar_proto(compar))

ptr is the returned void pointer. If key wasn't found in arr, the value would be None, but in this case we got a valid value.

Now we can convert it and access the value:

>>> cast(ptr, POINTER(c_int)).contents

Also, we can see that ptr points to the correct value inside arr:

>>> addressof(arr) + 12 * sizeof(c_int) == ptr