I want to call ac function from python using ctypes. From the documentation I don't understand how to pass pointer to vectors. The function I want to call is:
double f(int n, double* x)
{
int i;
double p=1;
for (i=0; i< n; i ++)
p = p * x[i];
return p;
}
I have modified the function with void pointer, so it becomes f(int, void*)
with an internal cast to double. I do the following:
def f(x):
n = len(x)
libc = '/path/to/lib.so'
cn = c_int(n)
px = pointer(x)
cx = c_void_p(px)
libc.restype = c_double
L = libc.f(cn, cx)
return L
I assume that x is a numpy array, but I am not sure how the numpy array are organized in the memory and if this is the best solution.
Edit:
None of the proposed methods work with my numpy array, maybe it is due to how I am defining the array:
x = np.array([], 'float64')
f = open(file,'r')
for line in f:
x = np.append(x,float(line))
but some of them work if I have an explicit list like [1,2,3,4,5]
, rather than a list that has been defined somewhere else and it is referred as x
Based on @Sven Marnach's answer :
#!/usr/bin/env python
import ctypes
import numpy as np
from numpy.ctypeslib import ndpointer
libf = ctypes.cdll.LoadLibrary('/path/to/lib.so')
libf.f.restype = ctypes.c_double
libf.f.argtypes = [ctypes.c_int, ndpointer(ctypes.c_double)]
def f(a):
return libf.f(a.size, np.ascontiguousarray(a, np.float64))
if __name__=="__main__":
# slice to create non-contiguous array
a = np.arange(1, 7, dtype=np.float64)[::2]
assert not a.flags['C_CONTIGUOUS']
print(a)
print(np.multiply.reduce(a))
print(f(a))
[ 1. 3. 5.]
15.0
15.0
Removing np.ascontiguousarray()
call produces the wrong result ( 6.0
on my machine).
You can call it like this:
#!python
from ctypes import *
#!python
from ctypes import *
# double f(int n, double* x)
f = CDLL('/path/to/lib.so').f
f.argtypes = [c_int, POINTER(c_double)]
f.restype = c_double
if __name__ == '__main__':
array = (c_double * 5)(1, 2, 3, 4, 5)
r = f(len(array), array)
print(r)
If you have numpy array, you can use numpy.array.ctypes.data_as
:
#!python
from ctypes import *
import numpy
# double f(int n, double* x)
f = CDLL('/path/to/lib.so').f
f.argtypes = [c_int, POINTER(c_double)]
f.restype = c_double
if __name__ == '__main__':
array = numpy.array([1, 2, 3, 4, 5])
r = f(array.size, array.astype(numpy.double).ctypes.data_as(POINTER(c_double)))
print(r)
or:
#!python
from ctypes import *
import numpy
# double f(int n, double* x)
f = CDLL('/path/to/lib.so').f
f.argtypes = [c_int, POINTER(c_double)]
f.restype = c_double
if __name__ == '__main__':
array = numpy.double([1, 2, 3, 4, 5])
r = f(array.size, array.ctypes.data_as(POINTER(c_double)))
print(r)
apparently I needed to specify the flag contigous to make it work
http://scipy-lectures.github.io/advanced/interfacing_with_c/interfacing_with_c.html
this is an extract from my code:
array_1d_double = numpy.ctypeslib.ndpointer(dtype=numpy.double, ndim=1,
flags='CONTIGUOUS')
libc.f.argtypes = [c_int, array_1d_double]
libc.f(n, x)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.