I'm trying to interface a shared c library with a python code. The interface with the library is something like
typedef struct{
int v1;
double* v2} input;
There are two other types like this one for configuration and the output type.
I had this structs in python using ctypes Structure like this:
class input(Structure):
_fields_ = [("v1",c_int),("v2",POINTER(c_double)]
The C code have some functions that receives a pointer to that structure and the argtypes are defined as in:
fun.argtypes = [constraints,input,POINTER(input)]
constraints is another structure with some int fields for configuration.
when I call the function I do in this way: first I update the v2 field in the input struct
input.v2 = generated_array.ctypes.data_as(POINTER(c_double))
Then I call with:
fun(constraints,input,byref(output))
The function prototype asks for struct and * to struct(output struct is similar to input) Then I want to access the results of fun stored in the v2 field of output. But I'm taking unexpected results. Is there a better(perhaps correct) way of do this?
I searched a lot here and read the documentation but i can't find what's wrong. I don't have any error messages, but the warnings that I receive from the shared lib seems to show that there are mistakes on this interfaces.
I guess I had found the problem. When I call the method a numpy array of complex is called. Then I create 4 vectors:
out_real = ascontiguousarray(zeros(din.size,dtype=c_double))
out_imag = ascontiguousarray(zeros(din.size,dtype=c_double))
in_real = ascontiguousarray(din.real,dtype = c_double)
in_imag = ascontiguousarray(din.imag,dtype = c_double)
where din is the input vector. I had tested the method this way:
print in_real.ctypes.data_as(POINTER(c_double))
print in_imag.ctypes.data_as(POINTER(c_double))
print out_real.ctypes.data_as(POINTER(c_double))
print out_imag.ctypes.data_as(POINTER(c_double))
and the result was:
<model.LP_c_double object at 0x1d81f80>
<model.LP_c_double object at 0x1d81f80>
<model.LP_c_double object at 0x1d81f80>
<model.LP_c_double object at 0x1d81f80>
seems that all of them are pointing to the same place.
After some changes, it work as expected
After several tests I found that the code was nearly correct in the first time. I was creating the Structure instance once and updating it's fields. I change to create a new instance at each call of fun. I also change all arrays types to be the equivalent ctypes type, this seems to make the function work as expected.
The print behavior still holds as in the test above, but the function seems to work even with this strange behavior. It is correct as pointed by @ericsun comment below.
fun.argtypes = [...,POINTER(input)]
andfun(..,input,byref(output))
is not the same interface. – HYRY Mar 15 '13 at 11:39LP_c_double
objects, that's the Python object address, not the address in the pointer. You only printed a temporary pointer object; at the next print it was already deallocated and the same address was reused. Look at thecontents
attribute, or just the[0]
index. – eryksun Mar 15 '13 at 13:48