【问题标题】:Python/C API - The result is not displayedPython/C API - 结果不显示
【发布时间】:2017-04-07 22:58:17
【问题描述】:

我想在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)

这似乎是对的,但是当我在终端中启动它时 - 没有任何反应,只是挂起没有任何活动。我会错过什么?

【问题讨论】:

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


    【解决方案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 扩展的人来说真的很棘手。

    【讨论】:

    • 非常感谢!你为我节省了很多时间)
    • @errfrom 不客气 :) 实际上我在运行脚本时遇到了分段错误,因此使用 gdb 进行调试非常容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 2015-10-30
    • 2020-05-05
    • 2016-07-22
    相关资源
    最近更新 更多