[英]ctypes: How to access array of structure returned by function?
我有一個 c++ API 函數,我需要使用 ctypes 從 python 調用它。
在我的 c++ libamo.h
中,我有struct
和function
的原型,如下所示,
typedef struct contain_t
{
uint8_t id;
uint16_t ele1;
uint16_t ele2;
uint16_t ele3;
uint16_t ele4;
float ele5;
} mycontain;
mycontain* get_result(void *context, int r, int c, unsigned char* rawdata);
在我的 c++ libamo.cpp
中,我聲明了結構的全局數組,
mycontain all_contain[50];
function mycontain* get_result()
填充結構數組,我通過打印結構的內容在 c++ 中對其進行了測試。
在ctypes
中:
libamo.so
。from ctypes import *
class mycontain(Structure):
_fields_ = [('id', c_uint),
('ele1',c_uint),
('ele2', c_uint),
('ele3', c_uint),
('ele4', c_uint),
('ele5', c_float) ]
ptr_cnt = POINTER(mycontain)
amo_get_result = libamo.get_result
amo_get_result.restype = ptr_cnt
amo_get_result.argtypeps = [c_void_p, c_int, c_int, c_char_p]
res = amo_get_result(amo_context, 300, 300, raw_val.ctypes.data_as(c_char_p))
我嘗試了以下方法從結構成員中獲取數據。
方法一:
output_res = res.contents
print(output_res.id, output_res.ele1, output_res.ele2, output_res.ele3, output_res.ele4, output_res.ele5)
在 output 我得到,對於上述元素
7208960 0.0 4128919 173 1049669215 21364736
方法2:嘗試鑄造
print(cast(output_res.id, POINTER(c_uint)))
output>><__main__.LP_c_uint object at 0x7f9450f3c0>
我的問題是, - 如何優雅地從結構數組中讀取數據。 我已經參考了多個 SO 帖子,大多數討論了訪問結構的單個實例的方法,而不是結構數組。
使用結構中的匹配類型。 c_uint
通常是 32 位的,因此您的 Python 結構的大小錯誤。
要訪問數組,請索引指針(例如output_res[0].id
)或使用切片。
這是一個帶有測試 DLL 的可重現示例:
測試.cpp
#include <stdint.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef struct contain_t
{
uint8_t id;
uint16_t ele1;
uint16_t ele2;
uint16_t ele3;
uint16_t ele4;
float ele5;
} mycontain;
mycontain all_contain[5];
extern "C"
API mycontain* get_result(void *context, int r, int c, unsigned char* rawdata) {
for(int i = 0; i < 50; ++i) {
all_contain[i].id = i;
all_contain[i].ele1 = i*2;
all_contain[i].ele2 = i*3;
all_contain[i].ele3 = i*4;
all_contain[i].ele4 = i*5;
all_contain[i].ele5 = i * 1.01;
}
return all_contain;
}
測試.py
from ctypes import *
class mycontain(Structure):
_fields_ = [('id', c_uint8), # use correct types
('ele1',c_uint16),
('ele2', c_uint16),
('ele3', c_uint16),
('ele4', c_uint16),
('ele5', c_float) ]
# Make a display representation for easy viewing
def __repr__(self):
return f'mycontain(id={self.id}, ele1={self.ele1}, ..., ele5={self.ele5:.2f})'
dll = CDLL('./test')
dll.get_result.argtypes = c_void_p, c_int, c_int, c_char_p
dll.get_result.restype = POINTER(mycontain)
res = dll.get_result(None, 300, 300, None)
print(res[:5]) # slice to appropriate size to get list of elements
Output:
[mycontain(id=0, ele1=0, ..., ele5=0.00), mycontain(id=1, ele1=2, ..., ele5=1.01), mycontain(id=2, ele1=4, ..., ele5=2.02), mycontain(id=3, ele1=6, ..., ele5=3.03), mycontain(id=4, ele1=8, ..., ele5=4.04)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.