calling c from python with ctypes: passing vectors

前端 未结 3 1945
忘了有多久
忘了有多久 2021-01-13 14:22

I want to call a c 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:



        
相关标签:
3条回答
  • 2021-01-13 14:41

    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))
    

    Output

    [ 1.  3.  5.]
    15.0
    15.0
    

    Removing np.ascontiguousarray() call produces the wrong result (6.0 on my machine).

    0 讨论(0)
  • 2021-01-13 14:49

    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)
    
    0 讨论(0)
  • 2021-01-13 15:01

    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)
    
    0 讨论(0)
提交回复
热议问题