tags:

views:

138

answers:

1

Currently I'm in the process of moving a performance bottleneck in my python code to c, to investigate peformance effects. This code will run a simulation, and report back the results to python via ctypes. However, I'm having problems getting my types to match up correctly.

Although I'm looking to solve this particular problem, I'm also on the lookout for more general advice on working with ctypes, as the documentation and procedure seems a bit thin.

I have the following c function:

extern "C" {
    void f( int* array, int arraylen ) {
        for(int i = 0; i < arraylen; i++) {
            array[i] = g() // mutate the value array[i];
        }
    }
}

And the following code in python:

import ctypes

plib   = ctypes.cdll.LoadLibrary('./mylib.so')
_f = plib.f
_f.restype  = None
_f.argtypes = [ ctypes.POINTER(ctypes.c_int), ctypes.c_int ]
seqlen = 50
buffer = ctypes.c_int * seqlen
_f( buffer, seqlen )

However, this snippet dies with the following traceback:

Traceback (most recent call last):
  File "particle.py", line 9, in <module>
    _f( buffer, seqlen )
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: expected LP_c_int instance instead of _ctypes.ArrayType
+2  A: 

Looks like you want the cast function:

The cast function can be used to cast a ctypes instance into a pointer to a different ctypes data type. cast takes two parameters, a ctypes object that is or can be converted to a pointer of some kind, and a ctypes pointer type. It returns an instance of the second argument, which references the same memory block as the first argument:

>>> a = (c_byte * 4)()
>>> a
<__main__.c_byte_Array_4 object at 0xb7da2df4>
>>> cast(a, POINTER(c_int))
<ctypes.LP_c_long object at ...>
>>>
Mark Rushakoff
Thanks Mark, your snippet was enough for me to figure out what the problem was, I'd omitted the parentheses from my array instantiation, which had triggered the type mismatch.
Andrew Walker