问题描述
这很奇怪,我试图包装一个我用 c 编写的函数以便在 python 中使用它,为了了解如何做到这一点,我举了一个例子:
cfunctions.c
:
double dotproduct(int dim,double a[dim],double b[dim]){
double res = 0;
for(int i = 0; i < dim; i++){
res = res + a[i]*b[i];
}
return res;
}
py_cfunctions.py
:
from ctypes import *
import numpy as np
# so_file genreated with:
# cc -fPIC -shared -o cfunctions.so cfunctions.c
so_file = 'MY_PATH/cfunctions.so'
py_cfunctions = CDLL(so_file)
c_double_p = POINTER(c_double)
# Preparing example
def dotproduct(n,a,b):
# Convert np.array to ctype doubles
a_data = a.astype(np.double)
a_data_p = a_data.ctypes.data_as(c_double_p)
b_data = b.astype(np.double)
b_data_p = b_data.ctypes.data_as(c_double_p)
# Compute result...
c_return = py_cfunctions.dotproduct(n,a_data_p,b_data_p)
if (c_return != -1):
return c_return
else:
return "C Function Failed,check inputs"
py_cfunctions.dotproduct.argtypes= [c_int,c_double_p,c_double_p]
有趣的是,代码似乎可以工作,但返回的值始终等于 n
。如果我在返回之前尝试打印 res
,我可以看到该值是正确的,但实际返回的值始终为 n
。我错过了什么?
>>> import py_cfunctions as pycf
>>> import numpy as np
>>> a = np.array([1,2,3,4])
>>> b = np.array([4,5,6,1])
>>> pycf.dotproduct(4,b)
4
解决方法
感谢@Mark Tolonen 的回答:
“在实现级别,整数在与浮点值不同的寄存器中返回。除非另有说明,否则 ctypes 假定返回值是 c_int。使用 ctypes 时,'显式优于隐式'。始终正确定义 .restype 和 .argtypes,并且你会遇到更少的问题。”
我必须明确定义函数的返回类型,将以下行添加到 pic_functions.py
:
py_cfunctions.dotproduct.restype = c_double