使用ctypes从python调用c:传递向量


问题内容

我想使用ctypes从python调用ac函数。从文档中,我不了解如何将指针传递给向量。我要调用的函数是:

double f(int n, double* x)
  {
    int i;
    double p=1;
    for (i=0; i< n; i ++) 
      p = p * x[i];
    return p;
  }

我用void指针修改了该函数,因此f(int, void*)内部强制转换为double。我执行以下操作:

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

我假设x是一个numpy数组,但是我不确定numpy数组在内存中的组织方式以及这是否是最佳解决方案。


编辑:

提议的方法均不适用于numpy数组,可能是由于我如何定义数组:

x = np.array([], 'float64')
f = open(file,'r')
for line in f:
  x = np.append(x,float(line))

但是如果我有一个明确的列表(例如)[1,2,3,4,5],而不是已经在其他位置定义的列表,则其中一些可以工作x


问题答案:

基于@Sven Marnach的答案

#!/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

删除np.ascontiguousarray()呼叫会产生错误的结果(6.0在我的机器上)。