如何使用 PyList return Python C API 扩展中的整数列表?
How to return a list of ints in Python C API extension with PyList?
我正在使用 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);
给了我一个带有两个随机整数的正确元组,正如预期的那样。然而,returning GetListTwoInts
方法中的列表给出了无效数字(看起来像一个参考值或指针?)。
我应该如何处理 return 实数值列表而不是 GetListTwoInts
方法?
您可以更改 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_New
和 PyList_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
指针。
我正在使用 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);
给了我一个带有两个随机整数的正确元组,正如预期的那样。然而,returning GetListTwoInts
方法中的列表给出了无效数字(看起来像一个参考值或指针?)。
我应该如何处理 return 实数值列表而不是 GetListTwoInts
方法?
您可以更改 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_New
和 PyList_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
指针。