2017-04-07 35 views
1

我想将C模块集成到Python中,因此我的选择落在了界面Python.h上。没有错误和警告编译的所有东西,所以我不明白是什么问题。Python/C API - 结果不显示

C面:

#include <python3.5m/Python.h> 
... 
#define PyInt_AsLong(x) (PyLong_AsLong((x))) 
typedef PyObject* Py; 

static Py getSumma(Py self, Py args){ 
    Py nums; 
    if (!PyArg_ParseTuple(args, "O", &nums)){ 
    return NULL; 
    } 
    size_t numsAmount = PyList_Size(args); 
    int32_t summa = 0; 

    for (size_t i = 0; i < numsAmount; i++){ 
    Py temp = PyList_GetItem(nums, i); 
    int32_t num = PyInt_AsLong(temp); 
    summa += num; 
    } 
    return Py_BuildValue("l", summa); 
} 

static PyMethodDef moduleMethods[] = { 
    {"getSumma", (PyCFunction)getSumma, METH_VARARGS, NULL}, 
    {NULL, NULL, 0, NULL} 
}; 

static PyModuleDef SummaLogic = { 
    PyModuleDef_HEAD_INIT, 
    "SummaLogic", 
    "", 
    -1, 
    moduleMethods 
}; 

PyMODINIT_FUNC PyInit_SummaLogic(void){ 
    return PyModule_Create(&SummaLogic); 
} 

setup.py:

from distutils.core import setup, Extension 

SummaLogic = Extension("SummaLogic", sources=['SummaLogic.c']) 
setup(ext_modules=[SummaLogic]) 

Python端:

from SummaLogic import getSumma 

if __name__ == "__main__": 
    a = [1, 2, 3] 
    b = getSumma(a) 
    print(b) 

这似乎是正确的,但是当我在终端启动它 - 没有任何反应,只是挂着没有任何活动。我可能会错过什么?

回答

1

它归结为PyList_Size并且您不检查那里的错误。

您可能想要在nums上使用它,而不是args作为参数。但是你用在args和一个非常有趣的事情发生了:

  • argstuple
  • 因此PyList_Size失败,返回-1
  • -1其转换为一个无符号size_t这可能导致非常数量巨大,可能是2**64-1
  • 因此,您的迭代运行“很长时间”,因为它需要相当长的时间迭代2**64-1项目(除了所有超出界限的内存访问)。

速战速决是使用:

Py_ssize_t listlength = PyList_Size(nums); /* nums instead of args */ 
if (listlength == -1) { /* check for errors */ 
    return NULL; 
} 
size_t numsAmount = (size_t)listlength /* cast to size_t only after you checked for errors */ 

但是你应该每个Python C API函数调用后检查什么的错误条件和测试它们,否则你会得到很多的不确定行为。此外,我可能会坚持定义的返回类型,而不是int32_tPyInt_AsLong返回long,这样您可能会在那里出现奇怪的铸造错误!),size_t,...和typedef PyObject* Py;对于定期编写C扩展的人来说非常棘手。

+0

非常感谢!您为我节省了很多时间) – errfrom

+0

@errfrom不客气:)我在运行脚本时遇到了分段错误,所以使用gdb很容易进行调试。 – MSeifert