为什么基于 C 的 Python 扩展总是 return 相同的值?
Why might a C-based Python extension always return the same value?
下面的代码看起来非常简单。一个整数被传递给 Python 中的函数,它在 C 中创建一个 PyList 然后填充它:
hello.c:
#include <Python.h>
PyObject* getlist(int *len)
{
printf("Passed to C: %d\n", *len);
PyObject *dlist = PyList_New(*len);
double num = 0.1;
for (int i = 0; i < *len; i++)
{
PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
num += 0.1;
}
return dlist;
}
static char helloworld_docs[] =
"Fill docs where possible\n";
static PyMethodDef helloworld_funcs[] = {
{"getlist", (PyCFunction)getlist, METH_VARARGS, helloworld_docs},
{NULL}
};
static struct PyModuleDef Helloworld =
{
PyModuleDef_HEAD_INIT,
"Helloworld", // module name
"NULL", // module documentation
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
helloworld_funcs
};
PyMODINIT_FUNC PyInit_helloworld(void)
{
return PyModule_Create(&Helloworld);
}
setup.py:
from distutils.core import setup
from distutils.extension import Extension
setup(name='helloworld',
version='1.0',
ext_modules=[Extension('helloworld', ['hello.c'])])
usepkg.py:
#!/usr/bin/python
import sys
import helloworld
print("Input to Python:", sys.argv[1])
print (helloworld.getlist(sys.argv[1]))
我使用
构建和安装
python3 setup.py build
python3 setup.py install
我没有发现任何错误。
当我测试它时出现了奇怪的行为。例如:
python3 usepkg.py 4
无论我给出什么值作为参数,输出总是相同的:
Input to Python: 4
Passed to C: 6
[0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6]
传递给C的值总是6。无论输入参数是int还是Py_ssize_t都是一样的。我错过了什么?
我很惊讶这里在构建时没有警告,函数的类型不应该是它们的原始类型,而是 PyObject*
——然后你将解析类型并执行你的函数
对您的功能进行调整:
PyObject* getlist(PyObject* self, PyObject* args)
{
int len;
if (!PyArg_ParseTuple(args, "i", &len)) {
return NULL;
}
printf("Passed to C: %d\n", len);
PyObject *dlist = PyList_New(len);
double num = 0.1;
for (int i = 0; i < len; i++)
{
PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
num += 0.1;
}
return dlist;
}
可以在 parsing arguments and building values 文档
中找到更多相关信息
您得到的数字可能是 PyObject*->ob_refcount
中 self
的值(对 C 模块的引用数)
在我的例子中,我看到了 4 个而不是 6 个,尽管我可能使用了不同版本的 python and/or 调用方法
下面的代码看起来非常简单。一个整数被传递给 Python 中的函数,它在 C 中创建一个 PyList 然后填充它:
hello.c:
#include <Python.h>
PyObject* getlist(int *len)
{
printf("Passed to C: %d\n", *len);
PyObject *dlist = PyList_New(*len);
double num = 0.1;
for (int i = 0; i < *len; i++)
{
PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
num += 0.1;
}
return dlist;
}
static char helloworld_docs[] =
"Fill docs where possible\n";
static PyMethodDef helloworld_funcs[] = {
{"getlist", (PyCFunction)getlist, METH_VARARGS, helloworld_docs},
{NULL}
};
static struct PyModuleDef Helloworld =
{
PyModuleDef_HEAD_INIT,
"Helloworld", // module name
"NULL", // module documentation
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
helloworld_funcs
};
PyMODINIT_FUNC PyInit_helloworld(void)
{
return PyModule_Create(&Helloworld);
}
setup.py:
from distutils.core import setup
from distutils.extension import Extension
setup(name='helloworld',
version='1.0',
ext_modules=[Extension('helloworld', ['hello.c'])])
usepkg.py:
#!/usr/bin/python
import sys
import helloworld
print("Input to Python:", sys.argv[1])
print (helloworld.getlist(sys.argv[1]))
我使用
构建和安装python3 setup.py build
python3 setup.py install
我没有发现任何错误。
当我测试它时出现了奇怪的行为。例如:
python3 usepkg.py 4
无论我给出什么值作为参数,输出总是相同的:
Input to Python: 4
Passed to C: 6
[0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6]
传递给C的值总是6。无论输入参数是int还是Py_ssize_t都是一样的。我错过了什么?
我很惊讶这里在构建时没有警告,函数的类型不应该是它们的原始类型,而是 PyObject*
——然后你将解析类型并执行你的函数
对您的功能进行调整:
PyObject* getlist(PyObject* self, PyObject* args)
{
int len;
if (!PyArg_ParseTuple(args, "i", &len)) {
return NULL;
}
printf("Passed to C: %d\n", len);
PyObject *dlist = PyList_New(len);
double num = 0.1;
for (int i = 0; i < len; i++)
{
PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
num += 0.1;
}
return dlist;
}
可以在 parsing arguments and building values 文档
中找到更多相关信息您得到的数字可能是 PyObject*->ob_refcount
中 self
的值(对 C 模块的引用数)
在我的例子中,我看到了 4 个而不是 6 个,尽管我可能使用了不同版本的 python and/or 调用方法