如何使用 PyList 在 Python C API 扩展中返回整数列表?

Posted

技术标签:

【中文标题】如何使用 PyList 在 Python C API 扩展中返回整数列表?【英文标题】:How to return a list of ints in Python C API extension with PyList? 【发布时间】:2018-06-03 17:13:26 【问题描述】:

我正在使用 Visual Studio 2015 C++ 项目和 Python 2.7 32 位构建 Python 扩展 (.pyd)。

这是我的.cpp 文件:

#include <Python.h>

static PyObject* GetTwoInts(PyObject* self, PyObject* args)

    srand(time(NULL));
    int random1 = rand() % 10;
    int random2 = rand() % 10;

    PyObject * python_val = Py_BuildValue("ii", random1, random2);
    return python_val;


static PyObject* GetListTwoInts(PyObject* self, PyObject* args)

    srand(time(NULL));
    int random1 = rand() % 10;
    int random2 = rand() % 10;

    PyObject *val1 = PyInt_FromLong(random1);
    PyObject *val2 = PyInt_FromLong(random2);

    PyObject *result = PyList_New(2);
    PyList_SetItem(result, 0, val1);
    PyList_SetItem(result, 1, val2);

    PyObject * python_val = Py_BuildValue("ii", result);
    return python_val;


PyMODINIT_FUNC initUtils(void)

    static PyMethodDef methods[] = 
         "GetTwoInts", GetTwoInts, METH_NOARGS,
        "Get two C ints as a Python tuple with two random numbers" ,

         "GetListTwoInts", GetListTwoInts, METH_NOARGS,
        "Get a list with two random numbers" ,
         NULL, NULL, 0, NULL ,

    ;

    PyObject *m = Py_InitModule("Utils", methods);

这是使用已编译扩展的 Python 源代码:

import sys
import Utils
print help(Utils)
print Utils.GetTwoInts()
print Utils.GetListTwoInts()

这是输出:

(4, 2)
(91213912, 91213912)

所以,正如预期的那样,Py_BuildValue("ii", random1, random2); 给了我一个包含两个随机整数的正确元组。但是,在 GetListTwoInts 方法中返回一个列表会给我无效的数字(看起来像引用值还是指针?)。

我应该怎么做才能在GetListTwoInts 方法中返回一个实数值列表?

【问题讨论】:

你为什么不返回result?这是你的清单。 @IgnacioVazquez-Abrams,谢谢。我只需要返回result 【参考方案1】:

您可以更改Py_BuildValue 的格式,以便它构建一个列表而不是一个元组。只需使用"[ii]" 而不是"ii" 作为第一个参数:

static PyObject* GetListTwoInts(PyObject* self, PyObject* args)

    srand(time(NULL));
    int random1 = rand() % 10;
    int random2 = rand() % 10;

    PyObject * python_val = Py_BuildValue("[ii]", random1, random2);
    return python_val;

如果要创建动态大小列表,可以使用PyList_NewPyList_SetItem

static PyObject* GetList(PyObject* self, PyObject* args)

    srand(time(NULL));
    int const N = 10;
    PyObject* python_val = PyList_New(N);
    for (int i = 0; i < N; ++i)
    
        int r = rand() % 10;
        PyObject* python_int = Py_BuildValue("i", r);
        PyList_SetItem(python_val, i, python_int);
    
    return python_val;

您问题中PyList 版本的问题是您在列表中使用Py_BuildValue("ii", result)。这会尝试创建一个包含两个整数的元组,其中第一个值是转换为整数的 result 指针。

【讨论】:

谢谢。但是,我想返回一个包含任意数量项目的列表,因此不能选择将每个项目作为参数提供给 Py_BuildValue。是否可以在不将每个项目作为参数的情况下返回整个列表? Py_BuildValue([i], [1,2,4..n]) 之类的东西? @AlexTereshenkov 我编辑了我的答案并添加了一个使用PyList_NewPyList_SetItem 来创建具有动态大小的列表的示例。 或使用PyList_Append,这可能是:PyObject *list = PyList_New(0); iterate through the array/list; PyList_Append(list, PyFloat_FromDouble(element)); return list;

以上是关于如何使用 PyList 在 Python C API 扩展中返回整数列表?的主要内容,如果未能解决你的问题,请参考以下文章

使用C语言为python编写动态模块--在C中实现python中的类

C++调用时python时,如何传入数组做为参数

Python C API 使用详解

使用 Python C API 实现 PyMyType_Check 方法?

python & c-c++扩展模块案例segmentfault

python-os模块使用