【问题标题】:Passing a Python list to C function using the Python/C API使用 Python/C API 将 Python 列表传递给 C 函数
【发布时间】:2019-08-30 22:12:46
【问题描述】:

我最近开始使用 Python/C API 来使用 C 代码为 Python 构建模块。我一直在尝试将 Python 数字列表传递给 C 函数,但没有成功:

asdf_module.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <Python.h>

int _asdf(int low, int high, double *pr)
    // ...

    for (i = 0; i < range; i++)
    {
        printf("pr[%d] = %f\n", i, pr[i]);
    }

    // ...

    return 0;
}

static PyObject*
asdf(PyObject* self, PyObject* args)
{
    int low, high;
    double *pr;
    // maybe something about PyObject *pr ?

    if (!PyArg_ParseTuple(args, "iiO", &low, &high, &pr))
        return NULL;

    // how to pass list pr to _asdf?

    return Py_BuildValue("i", _asdf(low, high, pr));
}

static PyMethodDef AsdfMethods[] =
{
     {"asdf", asdf, METH_VARARGS, "..."},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initasdf(void)
{
    (void) Py_InitModule("asdf", AsdfMethods);
}

使用 setup.py 构建模块:

from distutils.core import setup, Extension

module1 = Extension('asdf', sources = ['asdf_module.c'])

setup (name = 'asdf',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [module1])

使用 test_module.py 中的模块:

import asdf

print asdf.asdf(-2, 3, [0.7, 0.0, 0.1, 0.0, 0.0, 0.2])

但是,我得到的输出是:

pr[0] = 0.000000

pr[1] = 0.000000

pr[2] = 0.000000

pr[3] = 0.000000

pr[4] = 0.000000

pr[5] = -nan

另外,不是 _asdf 返回 0,而是如何返回 n 值的数组(其中 n 是一个固定数字)?

【问题讨论】:

  • 一方面,o 参数用于获取PyObject *。所以你需要修复它,并继续解析。
  • 如果您可以发布单独的问题而不是将您的问题合并为一个问题,则最好。这样,它可以帮助人们回答您的问题,也可以帮助其他人至少寻找您的一个问题。如果您还有其他问题,我建议您前往右上角的小 按钮。谢谢!

标签: python c


【解决方案1】:

这个例子将告诉你如何

  1. 获取列表长度
  2. double 的数组分配存储空间
  3. 获取列表的每个元素
  4. 将每个元素转换为double
  5. 将每个转换后的元素存储在数组中

代码如下:

#include "Python.h"

int _asdf(double pr[], int length) {
    for (int index = 0; index < length; index++)
        printf("pr[%d] = %f\n", index, pr[index]);
    return 0;
}

static PyObject *asdf(PyObject *self, PyObject *args)
{
    PyObject *float_list;
    int pr_length;
    double *pr;

    if (!PyArg_ParseTuple(args, "O", &float_list))
        return NULL;
    pr_length = PyObject_Length(float_list);
    if (pr_length < 0)
        return NULL;
    pr = (double *) malloc(sizeof(double *) * pr_length);
    if (pr == NULL)
        return NULL;
    for (int index = 0; index < pr_length; index++) {
        PyObject *item;
        item = PyList_GetItem(float_list, index);
        if (!PyFloat_Check(item))
            pr[index] = 0.0;
        pr[index] = PyFloat_AsDouble(item);
    }
    return Py_BuildValue("i", _asdf(pr, pr_length));
}

注意:删除空格和大括号以防止代码滚动。

测试程序

import asdf
print asdf.asdf([0.7, 0.0, 0.1, 0.0, 0.0, 0.2])

输出

pr[0] = 0.700000
pr[1] = 0.000000
pr[2] = 0.100000
pr[3] = 0.000000
pr[4] = 0.000000
pr[5] = 0.200000
0

【讨论】:

  • 完成后一定要释放pr(用malloc分配),否则会出现内存泄漏。
【解决方案2】:

这会正确释放内存吗?

PyObject *res;
res = Py_BuildValue("i", _asdf(pr, pr_length));
free(pr);
return res;

【讨论】:

    猜你喜欢
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 2021-11-03
    • 2012-05-25
    • 2014-02-22
    • 2012-03-16
    相关资源
    最近更新 更多