简体   繁体   English

Ctypes:将返回的指针映射到结构

[英]Ctypes: Mapping a returned pointer to a structure

I have tried reading all the questions/answers on this topic but I could not get anything to work.我已尝试阅读有关此主题的所有问题/答案,但无法进行任何工作。 All I am trying to do is send a structure to a shared object, and then have it returned and be accessible.我要做的就是将一个结构发送到一个共享的 object,然后让它返回并可以访问。

I have managed to create a structure OK, and I can pass it fine to the shared object.我已经成功地创建了一个结构,我可以将它很好地传递给共享的 object。 I know this as it works fine if returning a specific value from the structure.我知道这一点,因为如果从结构中返回特定值,它工作正常。 The structure definition in Python can be seen below: Python中的结构体定义如下:

class ROW(ctypes.Structure):
    _fields_ = [("Address",ctypes.c_int16),
                ("FirstRegister",ctypes.c_int16),
                ("NumberOfRegisters",ctypes.c_int16),
                ("Sampling", ctypes.c_int16)]

class CONNECTOR(ctypes.Structure):
    _fields_ = [("NumberOfRows", ctypes.c_int16),
                ("Rows", ROW * 200)]

# Initialise an array of connectors (CON1, CON2, CON11, CON12)
ConArray = CONNECTOR * 4
con = ConArray()

# Initialise an array of ROW struct
RowArray = ROW * 200
row = RowArray()

I then populate the structure with data from an SQLite database and can access the specific data using con[n].Rows[m].Address etc.然后,我使用 SQLite 数据库中的数据填充结构,并可以使用con[n].Rows[m].Address等访问特定数据。

I am currently trying to just send one connector at a time, and return the exact same structure.我目前正在尝试一次只发送一个连接器,并返回完全相同的结构。

The relevant code can be seen below:相关代码如下:

testlib = ctypes.cdll.LoadLibrary('_example.so')
x = testlib.square_array
x.argtype = ctypes.POINTER(CONNECTOR)
x.restype = ctypes.POINTER(CONNECTOR)

y = x(ctypes.byref(con[0]))

I have tried many different methods of calling the function but this one seems to be the most promising.我尝试了许多不同的方法来调用 function 但这似乎是最有希望的。 The problem is when I try and then access specific values with y.Rows[0].Address[0] , an error occurs: AttributeError: 'LP_CONNECTOR' object has no attribute 'Rows' .问题是当我尝试然后使用y.Rows[0].Address[0]访问特定值时,会发生错误: AttributeError: 'LP_CONNECTOR' object has no attribute 'Rows'

If instead, I just call the function directly:相反,我只是直接调用 function :

x = testlib.square_array(ctypes.byref(con[0]))

I receive an int which I assume represents a memory address, eg: 35664848 .我收到一个int ,我假设它代表一个 memory 地址,例如: 35664848

I have tried all sorts of options but I am quite unfamiliar with C (a colleague will be handling all the C side of code).我尝试了各种选择,但我对 C 非常不熟悉(一位同事将处理代码的所有 C 方面)。 Is there any proposed solutions?有没有建议的解决方案? I feel like I am just missing one small thing, but it has took me many days just to reach this point.我觉得我只是错过了一件小事,但我花了很多天才达到这一点。

Update: Added C code更新:添加了 C 代码

The C code can be seen below: C代码如下:

example.c:示例.c:

 #include "example.h"

 CONNECTOR* square_array(CONNECTOR* con)
 {
    printf("Value of Row 0 Address%i\n",con->Rows[0].Address);
    return (con);
 }

example.h:例子.h:

struct ROW;
struct CONNECTOR;

typedef struct {
    short int Address;
    short int FirstRegister;
    short int NumberOfRegisters;
    short int Sampling; 
}ROW;

typedef struct {
    short int NumberOfRows;
    ROW Rows[200];
}CONNECTOR;

CONNECTOR Connectors[4];

I already created a small example of my own.我已经创建了一个自己的小例子。 After taking a closer look at the Python code, I could figure out the function header (and I also added some dummy body).在仔细查看Python代码后,我可以找出 function header (我还添加了一些假体)。

The problem is simple, the function returns a CONNECTOR pointer, in order to access its members, you need to "dereference" it first, otherwise you'll get the AttributeError .问题很简单,function 返回一个CONNECTOR指针,为了访问它的成员,你需要先“取消引用”它,否则你会得到AttributeError Here's your code (a little bit modified):这是您的代码(稍作修改):

testlib = ctypes.cdll.LoadLibrary("_example.so")
testfunc = testlib.square_array
testfunc.argtypes = (ctypes.POINTER(CONNECTOR),)
testfunc.restype = ctypes.POINTER(CONNECTOR)

pconnector0 = testfunc(ctypes.byref(con[0]))
connector0 = pconnector0.contents
print(connector0.NumberOfRows)
print(connector0.Rows[0].Address)

The "secret" lies in pconnector0.contents which performs the "dereferencing". “秘密”在于执行“取消引用”的pconnector0.contents

As a side note the line of code y.Rows[0].Address[0] will trigger a TypeError because of the [0] at the end: Address is an int and can't be indexed (doesn't define __getitem__ ).作为旁注,代码行y.Rows[0].Address[0]将触发TypeError因为末尾的[0]Address is an int and can't be indexed (doesn't define __getitem__ ) .

Regarding the second approach (calling the function directly), it's the same problem.关于第二种方法(直接调用function),也是同样的问题。 Here's some working code:这是一些工作代码:

pconnector1 = testlib.square_array(ctypes.byref(con[0]))
connector1 = pconnector1.contents
print(type(connector1))

Notes :备注

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM