从 Python 调用 C:传递 numpy 指针列表

2024-01-03

我有数量可变的 numpy 数组,我想将其传递给 C 函数。我设法传递了每个单独的数组(使用<ndarray>.ctypes.data_as(c_void_p)),但数组的数量可能会相差很大。

我想我可以在列表中传递所有这些“指针”并使用PyList_GetItem()C 代码中的函数。它的工作原理就像一个魅力,只是所有元素的值都不是我通常在将它们作为函数参数传递时获得的指针。

不过,如果我有:

from numpy import array
from ctypes import py_object

a1 = array([1., 2., 3.8])
a2 = array([222.3, 33.5])

values = [a1, a2]

my_cfunc(py_object(values), c_long(len(values)))

我的 C 代码如下所示:

void my_cfunc(PyObject *values)
{
    int i, n;

    n = PyObject_Length(values)
    for(i = 0; i < n; i++)
    {
        unsigned long long *pointer;
        pointer = (unsigned long long *)(PyList_GetItem(values, i);
        printf("value 0 : %f\n", *pointer);
    }
}

打印的值都是0.0000

我尝试了很多不同的解决方案,使用ctypes.byref(), ctypes.pointer()等等。但我似乎无法检索真正的指针值。我什至有这样的印象:c_void_p()被截断为 32 位...

虽然有很多关于将 numpy 指针传递给 C 的文档,但我在 Python 列表中没有看到任何有关 c_types 的内容(我承认这可能看起来很奇怪......)。

有什么线索吗?


经过几个小时的阅读多页文档并深入研究 numpy 包含文件后,我终于成功地理解了它的工作原理。由于我花费了大量时间寻找这些确切的解释,因此我提供以下文本以避免任何人浪费时间。

我重复一下这个问题:

如何将 numpy 数组列表从 Python 传输到 C

(我还假设您知道如何在 Python 中编译、链接和导入 C 模块)

通过一个Numpy从 Python 到 C 的数组相当简单,只要将其作为 C 函数中的参数传递即可。你只需要在Python中做这样的事情

from numpy import array
from ctypes import c_long

values = array([1.0, 2.2, 3.3, 4.4, 5.5])

my_c_func(values.ctypes.data_as(c_void_p), c_long(values.size))

C 代码可能如下所示:

void my_c_func(double *value, long size)
{
    int i;
    for (i = 0; i < size; i++)
        printf("%ld : %.10f\n", i, values[i]);
}

这很简单......但是如果我有可变数量的数组怎么办?当然,我可以使用解析函数参数列表的技术(许多例子堆栈溢出),但我想做一些不同的事情。

我想将所有数组存储在一个列表中,并将该列表传递给 C 函数,然后让 C 代码处理所有数组。

事实上,它非常简单、容易且连贯......一旦您了解它是如何完成的!有一个非常简单的事实需要记住:

列表/元组/字典的任何成员都是 Python 对象...在代码的 C 端!

你不能指望直接通过pointer正如我最初错误地认为的那样。一旦说过,这听起来很简单:-)不过,让我们编写一些Python代码:

from numpy import array

my_list = (array([1.0, 2.2, 3.3, 4.4, 5.5]),
           array([2.9, 3.8. 4.7, 5.6]))

my_c_func(py_object(my_list))

好吧,您不需要更改列表中的任何内容,但您需要指定将列表作为PyObject争论。

以下是如何在 C 中访问所有这些内容。

void my_c_func(PyObject *list)
{
    int i, n_arrays;

    // Get the number of elements in the list
    n_arrays = PyObject_Length(list);

    for (i = 0; i LT n_arrays; i++)
    {
        PyArrayObject *elem;
        double *pd;

        elem = PyList_GetItem(list,
                              i);
        pd = PyArray_DATA(elem);
        printf("Value 0 : %.10f\n", *pd);
    }
}

解释 :

  • 该列表作为指向PyObject
  • 我们使用以下方法从列表中获取数组的数量PyObject_Length()功能。
  • PyList_GetItem() always返回一个PyObject(实际上是一个void *)
  • 我们使用以下方法检索指向数据数组的指针PyArray_DATA() macro.

通常情况下,PyList_GetItem()返回一个py对象 *,但是,如果你看看Python.h and ndarraytypes.h,您会发现它们都定义为(我已经扩展了宏!):

typedef struct _object {
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

And the PyArray对象……一模一样。不过,在这个级别上它是完全可以互换的。 ob_type 的内容对于这两个对象都是可访问的,并且包含操作任何通用 Python 对象所需的所有内容。我承认我在调查过程中使用了其中一名成员。这struct member tp_name是包含对象名称的字符串...以明文形式表示;相信我,这很有帮助!这就是我发现每个列表元素包含的内容的方式。

虽然这些结构不包含任何其他内容,但我们如何访问 this 的指针ndarray目的 ?简单地使用对象宏...它使用扩展结构,允许编译器知道如何访问附加对象的元素,在ob_type指针。这PyArray_DATA()宏定义为:

#define PyArray_DATA(obj) ((void *)((PyArrayObject_fields *)(obj))->data)

在那里,它正在投射PyArayObject * as a PyArrayObject_fields *这个最新的结构很简单(简化并扩展了宏!):

typedef struct tagPyArrayObject_fields {
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
    char *data;
    int nd;
    npy_intp *dimensions;
    npy_intp *strides;
    PyObject *base;
    PyArray_Descr *descr;
    int flags;
    PyObject *weakreflist;
} PyArrayObject_fields;

正如您所看到的,该结构的前两个元素与PyObject and PyArray对象,但附加元素可以是已解决使用这个定义。直接访问这些元素很诱人,但这是一种非常糟糕且危险的做法,不仅仅是强烈劝阻。您必须使用宏,而不用担心所有这些结构中的细节和元素。我只是觉得你可能会对某些人感兴趣内部结构.

请注意,所有PyArray对象宏记录在http://docs.scipy.org/doc/numpy/reference/c-api.array.html http://docs.scipy.org/doc/numpy/reference/c-api.array.html

例如,一个的大小PyArray对象可以使用宏来获取PyArray_SIZE(PyArrayObject *)

最后,一旦您了解了它,它就非常简单且符合逻辑:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Python 调用 C:传递 numpy 指针列表 的相关文章

  • 如何忽略传递给函数的意外关键字参数?

    假设我有一些功能 f def f a None print a 现在 如果我有一本字典 比如dct a Foo 我可以打电话f dct 并得到结果Foo打印 但是 假设我有一本字典dct2 a Foo b Bar 如果我打电话f dct2
  • 如何移动我的图像? python 3.10.4 pygame

    我会移动我的图像 图像是matiskinfinal png 我尝试将像素添加到 x 或其他我不知道它是什么的东西 因为我真的是 python 的初学者 pygame但是是 x x 变化 但图像没有移动 import os import py
  • pip 安装失败,SSL 证书验证失败 (_ssl.c:833)

    我无法通过 pip install 安装任何外部 python 模块 我已经正确安装了 python 但如果我使用 pip install 它会显示此错误 这是我运行后的代码pip install pytesseract C Users 1
  • Python sqlite3参数化删除表

    我在 python 中删除 sqlite3 表时遇到问题 我正在使用标准sqlite3模块 self conn sqlite3 connect sql drop table self conn execute sql u table nam
  • 在 Python 中绘制分类数据的三个维度

    我的数据包含三个我试图可视化的分类变量 城市 五个之一 职业 四种之一 血型 四种之一 到目前为止 我已经成功地以一种我认为易于使用的方式对数据进行了分组 import numpy as np pandas as pd Make data
  • Spyder 导入模块出错

    我正在尝试在 Spyder 中使用 sklearn 一开始 当我尝试导入它时 我收到 ImportError No module named sklearn 然后我用 PYTHONPATH 管理器设置 PATH 然后使用工具菜单中的 更新模
  • 如何使用 HTTP 标头发送非英语 unicode 字符串?

    我是 HTTP 相关问题的新手 我的问题是在 iOS 开发中 我想使用 HTTP 标头发送一个字符串 所以我使用 httpRequest setValue nonEnglishString forHTTPHeaderField custom
  • 小数缓存是Python规范中定义的还是一个实现细节?

    Python 似乎有一个所谓的 小数字缓存 用于存储 5 到 256 范围内的数字 我们可以使用以下程序来演示这一点 for i in range 7 258 if id i id i 0 print i is cached else pr
  • 检测/删除 Python 2 + GTK 中不成对的代理字符

    在Python 2 7中我可以成功转换Unicode字符串 abc udc34xyz 转换为 UTF 8 结果是 abc xed xb0 xb4xyz 但是当我将 UTF 8 字符串传递给例如时 pango parse markup or
  • 如何在Python中求和

    我想知道如何在 python 中表示总和而不需要像这样的循环here http docs scipy org doc scipy reference tutorial optimize html 我们有 def rosen x The Ro
  • python-polars 通过分隔符将字符串列拆分为许多列

    在 pandas 中 以下代码会将 col1 中的字符串拆分为许多列 有没有办法在极地做到这一点 d col1 a b c d a b c d df pd DataFrame data d df a b c d df col1 str sp
  • 使用 3d 对象作为 3d 散点图中的标记 - Python

    使用下面的代码 我尝试模拟一个用罐头制成的碗 我希望每个标记都是一个罐头 最好的方法是什么 我真的很感激任何建议 谢谢 import pylab import numpy as np from math import pi sin cos
  • PyCharm 无法识别字典值类型

    我有一个简单的代码片段 其中我将字典值设置为空列表 new dict for i in range 1 13 new dict i 现在 如果在下一行的循环内我会输入new dict i 并添加一个点 我希望 PyCharm 向我显示可用于
  • 如何绘制多类分类器的精度和召回率?

    我正在使用 scikit learn 我想绘制精度和召回曲线 我正在使用的分类器是RandomForestClassifier scikit learn 文档中的所有资源都使用二元分类 另外 我可以绘制多类的 ROC 曲线吗 另外 我只找到
  • Python 中的十进制到二进制半精度 IEEE 754

    我只能使用以下命令将十进制转换为二进制单精度 IEEE754struct pack模块 或者使用相反的方法 float16 或 float32 numpy frombuffer 是否可以使用 Numpy 将十进制转换为二进制半精度浮点数 我
  • 如何将 fields 参数传递到 Google Drive Python API 调用中

    I have results drive service files list body execute where body q query string maxResults 1 为了提高性能 我想限制返回的字段 如下所述 https
  • 如何保持 python 3 脚本 (Bot) 运行

    不是母语英语 抱歉 英语可能很蹩脚 我也是编程新手 您好 我正在尝试使用 QueryServer 连接到 TeamSpeak 服务器来创建机器人 经过几天的努力 它有效 只有 1 个问题 而我却被这个问题困扰了 如果您需要检查 这是我正在使
  • Matplotlib 中的 TwoSlopeNorm 未按预期工作

    我正在尝试创建一个具有发散颜色图的绘图 该颜色图在零附近不对称 In this https stackoverflow com a 20146989 6288682例如 DivergingNorm函数被使用并产生我想要的 然而 我使用的是更
  • 在至少 7 天内连续三天登录该产品的用户

    我有一个用于用户参与的数据框 df 如下所示 time stamp user id 2013 01 01 10 05 23 1 2013 01 03 16 35 23 1 2013 01 06 11 06 35 1 2013 01 10 1
  • django admin 中内联模型的分页器

    我有这个简单的 django 模型 由一个传感器和特定传感器的值组成 每个日射强度计的值数量很多 gt 30k 是否可以以某种方式分页PyranometerValues在特定日期或一般情况下将分页器应用于管理内联视图 class Pyran

随机推荐