微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么基于C的Python扩展总是返回相同的值?

如何解决为什么基于C的Python扩展总是返回相同的值?

以下代码似乎非常简单。将一个整数传递给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_refcountself中的值(对C模块的引用数)

在我的情况下,我看到的是4而不是6,尽管我可能使用了不同版本的python和/或调用方法

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。