Python / C API - 不显示结果

时间:2017-04-07 22:58:18

标签: python c python-3.x python-c-api

我想在Python中集成C模块,所以我的选择落在了Python.h接口上。所有编译都没有错误和警告,所以我无法理解问题是什么。

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 个答案:

答案 0 :(得分:1)

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

您可能希望在nums上使用它,而不是args作为参数。但是你在args上使用了一件非常有趣的事情:

  • argstuple
  • 因此PyList_Size失败并返回-1
  • -1投放到无标记的size_t,这可能会导致非常大的数字,可能是2**64-1
  • 因此你的迭代运行了很长时间&#34;因为迭代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扩展名的人来说非常棘手。