【问题标题】:How do i read the values of a returned pointer from ctypes?我如何从 ctypes 读取返回指针的值?
【发布时间】:2022-11-30 03:49:21
【问题描述】:

我目前正在与 ctypes 作斗争。我能够将 python 列表转换为浮点数组并将其提供给 C 函数。但我无法弄清楚如何将这个数组从 C 函数返回到 python 列表......
Python代码

class Point(ctypes.Structure):
    _fields_= [("a", ctypes.c_float * 4),
               ("aa", ctypes.c_int)]

floats = [1.0, 2.0, 3.0, 4.0] 
FloatArray4 = (ctypes.c_float * 4)
parameter_array = FloatArray4(*floats)

test1 = clibrary.dosth
test1.argtypes = [ctypes.c_float * 4, ctypes.c_int]
test1.restype = ctypes.POINTER(Point)
struc = test1(parameter_array, 9)

p = (struc.contents.a)
print(p)
clibrary.free_memory(struc)

C 函数基本上将 parameter_array 放入结构 ant 返回结构.. C代码:

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

struct a{float *a;
        int aa;
        } ;

struct a *dosth(float *lsit, int x){
    struct a *b = malloc(200000);
    b -> a = lsit;
    b -> aa = 3;
    return b;
}
void free_memory(struct a *pointer){
    free(pointer);
}

Python 中 print(p) 的输出是:

<__main__.c_float_Array_4 object at 0x000001FE9EEA79C0>

我如何获得这些值?

【问题讨论】:

  • 对不起,不知道..
  • C 结构中的“a”是指向浮点数(或浮点数数组)的指针。为了匹配这个,在 ctypes 结构中它必须是一个“ctypes.POINTER(ctypes.c_float)”。 ctypes 调用的参数类型相同。
  • 太感谢了!!我现在可以使用 p[i] 访问奇异值了!有没有办法将这些指针的值保存到 python 列表中?
  • 使用一片。例如,p[:4] 将构建前 4 个值的列表。

标签: python arrays c pointers ctypes


【解决方案1】:

切片 ctypes 指针将生成内容的 Python 列表。由于指针不知道它指向多少项,因此您需要知道大小,通常是通过另一个参数:

>>> import ctypes as ct
>>> f = (ct.c_float * 4)(1,2,3,4)
>>> f
<__main__.c_float_Array_4 object at 0x00000216D6B7A840>
>>> f[:4]
[1.0, 2.0, 3.0, 4.0]

这是一个基于您的代码的充实示例:

测试.c

#include <stdlib.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

struct Floats {
    float *fptr;
    size_t size;
};

API struct Floats *alloc_floats(float *fptr, size_t size) {
    struct Floats *pFloats = malloc(sizeof(struct Floats));
    pFloats->fptr = fptr;
    pFloats->size = size;
    return pFloats;
}

API void free_floats(struct Floats *pFloats) {
    free(pFloats);
}

测试.py

import ctypes as ct

class Floats(ct.Structure):
    _fields_= (('fptr', ct.POINTER(ct.c_float)),  # Pointer, not array.
               ('size', ct.c_int))  # Used to know the size of the array pointed to.
    # Display routine when printing this class.
    # Note the slicing of the pointer to generate a Python list.
    def __repr__(self):
        return f'Floats({self.fptr[:self.size]})'

dll = ct.CDLL('./test')
dll.alloc_floats.argtypes = ct.POINTER(ct.c_float), ct.c_size_t
dll.alloc_floats.restype = ct.POINTER(Floats)
dll.free_floats.argtypes = ct.POINTER(Floats),
dll.free_floats.restype = None

data = (ct.c_float * 4)(1.0, 2.0, 3.0, 4.0)
p = dll.alloc_floats(data, len(data))
print(p.contents)
dll.free_floats(p)

输出:

Floats([1.0, 2.0, 3.0, 4.0])

【讨论】:

    猜你喜欢
    • 2013-04-03
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多