簡體   English   中英

ctypes:如何訪問 function 返回的結構數組?

[英]ctypes: How to access array of structure returned by function?

我有一個 c++ API 函數,我需要使用 ctypes 從 python 調用它。
在我的 c++ libamo.h中,我有structfunction的原型,如下所示,

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM