Python C扩展实现标准差
我正在写一个C语言扩展,用来计算标准差。因为要处理的数据量很大,所以性能非常重要。我在从列表中获取项目后,搞不清楚怎么得到pyobject的值。这是我第一次为Python写C语言扩展,任何帮助都非常感谢。显然,我不知道怎么正确使用代码示例按钮 :(
这是我目前的进展:
#include <Python.h>
static PyObject*
func(PyObject *self, PyObject *args)
{
PyObject *list, *item;
Py_ssize_t i, len;
if (!PyArg_UnpackTuple(args, "func", 1, 1, &list)){
return NULL;
}
printf("hello world\n");
Py_INCREF(list);
len = PyList_GET_SIZE(list);
for (i=0;i<len;i++){
item = PyList_GET_ITEM(list, i);
PyObject_Print(item,stdout,0);
}
return list;
}
static char func_doc[] = "This function calculates standard deviation.";
static PyMethodDef std_methods[] = {
{"func", func, METH_VARARGS, func_doc},
{NULL, NULL}
};
PyMODINIT_FUNC
initstd(void)
{
Py_InitModule3("std", std_methods, "This is a sample docstring.");
}
6 个回答
1
你有没有想过用 cython 来写你的扩展功能?它非常适合这种情况。
1
一旦你有了 item
,你可以通过 PyNumber_Float 来获取它的浮点值:
PyObject* floatitem = PyNumber_Float(item);
接下来,你需要检查是否有错误并在出错时退出(if(!floatitem) return 0
-- 或者用 goto
跳转到一个地方,那里可以减少你在代码前面部分可能增加的引用计数,比如在你的例子中是 list
)。如果没有错误,PyFloat_AsDouble 会给你所需的 double
值,以便在你后面的 C 代码循环中使用:
double ditem = PyFloat_AsDouble(floatitem);
之后你可以减少 floatitem
的引用计数,然后继续你的工作。不要太担心 PyNumber_Float
的转换开销 -- 如果你一开始传入的是浮点数列表,那就不会有任何开销;-)。如果你还是担心(如果有人传入非浮点数需要转换时宁愿报错),你可以使用 PyFloat_Check
,但我建议至少对 int
和 long
类型做特殊处理,否则会让用户感到困惑和不满;-)。同样,我也强烈建议你学习并使用 PySequence_Fast 及其相关函数,而不是让用户惊讶于你特别要求列表而不是其他类型的序列!-)