Reputation: 2594
Source of my C dll:
#include<stdio.h>
typedef struct {
int nums[5];
int tp;
} Sample;
float read_float(Sample s, float* arg){
return arg[1];
}
Source of Python code calling it:
from ctypes import *
class PySample(Structure):
_fields_ = [("nums", c_int * 5),
("tp", c_int)]
if __name__ == "__main__":
libp = CDLL(r"PathToMyDLL")
rf = libp.read_float
rf.restype = c_float
s = PySample()
for i in range(5):
s.nums[i] = (11,22,33,44,55)[i]
s.tp = 101
print(rf(s, (c_float*3)(0.4, 0.5, 0.6)))
After compiling with gcc -shared and running the Python code I get some random small number. However if I change signature of C function to:
float read_float(float* arg, Sample s)
and corresponding Python print call to:
print(rf((c_float*3)(0.4, 0.5, 0.6), s))
(that is changing order of arguments in both definition and function call) then I get correct 0.5
That isn't desired behavior. Any ideas what I am doing wrong here and why it is happening?
(Python 3.4.1 for 64bit Windows and C code is compiled with gcc 4.8.1 (MinGw-W64))
Upvotes: 1
Views: 359
Reputation: 178021
If you add an argtypes
declaration, your examples work correctly when compiled 32-bit and used with 32-bit Python:
rf.argtypes = [PySample, POINTER(c_float)]
But in 64-bit Python, if fails. I found that changing the argtypes
to use a pointer to the structure made it work, even though C is passing the structure by value.
rf.argtypes = [POINTER(PySample), POINTER(c_float)]
BUT, If I changed your functions to modify the structure, it modified it in Python as well. Calling the function from C and actually passing by value did not modify the structure in the caller as expected, so this seems like a bug in 64-bit ctypes
.
Upvotes: 2