Ctypes:将返回的指针映射到结构 [英] Ctypes: Mapping a returned pointer to a structure

查看:80
本文介绍了Ctypes:将返回的指针映射到结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试阅读有关此主题的所有问题/答案,但无法进行任何工作。我要做的就是将结构发送到共享库,然后将其返回并可以访问。



我设法创建了一个结构,好了,我可以很好地将其传递给共享库。我知道这一点,因为如果从结构中返回特定值,它将很好地工作。 Python中的结构定义如下所示:

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

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

#初始化连接器数组(CON1,CON2,CON11,CON12)
ConArray = CONNECTOR * 4
con = ConArray()

#初始化ROW结构数组
RowArray = ROW * 200
row = RowArray()

然后我用来自SQLite数据库的数据填充结构,并可以使用 con [n] .Rows [m] .Address

$访问特定数据。 b
$ b

我目前正在尝试一次只发送一个连接器,并返回完全相同的结构。



T相关代码如下:

  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 ]))

我尝试了许多不同的方法来调用该函数,但这似乎是最有效的方法有希望。问题是当我尝试然后使用 y.Rows [0] .Address [0] 访问特定值时,发生错误: AttributeError:' LP_CONNECTOR'对象没有属性'Rows'



如果相反,我直接调用该函数:

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

我收到一个 int ,我认为它表示一个内存地址,例如: 35664848



我尝试了各种选择,但我对C非常不熟悉(一位同事将处理C的所有代码)。有没有建议的解决方案?我觉得我只是想念一件事,但花了我很多天才达到这一点。



更新:添加了C代码



C代码如下所示:



example.c:

  #include example.h 

CONNECTOR * square_array(CONNECTOR * con)
{
printf (行0地址%i\n的值,con->行[0]。地址);
收益(续);
}

example.h:

 结构ROW; 
结构连接器;

typedef结构{
short int地址;
short int FirstRegister;
short int NumberOfRegisters;
short int采样;
} ROW;

typedef结构{
short int NumberOfRows;
ROW Rows [200];
}连接器;

连接器[4];


解决方案

我已经创建了一个自己的小例子。仔细研究 Python 代码之后,我可以弄清楚函数头(并且还添加了一些虚拟主体)。



问题很简单,该函数返回一个 CONNECTOR 指针,为了访问其成员,您需要先对其进行解除引用,否则将获得 AttributeError 。这是您的代码(稍作修改):

  testlib = ctypes.cdll.LoadLibrary( _ example.so)
testfunc = testlib.square_array
testfunc.argtype = 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)

秘密位于 pconnector0.contents 中,它执行取消引用。 / p>

请注意,代码行 y.Rows [0] .Address [0] 将触发 TypeError 因为结尾处的 [0] 地址 int ,并且无法建立索引(未定义 __ getitem __ )。



关于第二种方法(直接调用该函数),这是同样的问题。这是一些工作代码:

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

注意:我在 Win10 x64 上使用了 Python 2.7.10 ,但此处的任何内容都不应该是 Python 版本或特定于平台的。


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.

I have managed to create a structure OK, and I can pass it fine to the shared 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:

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.

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. 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'.

If instead, I just call the function directly:

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

I receive an int which I assume represents a memory address, eg: 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). 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

The C code can be seen below:

example.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:

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).

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. Here's your code (a little bit modified):

testlib = ctypes.cdll.LoadLibrary("_example.so")
testfunc = testlib.square_array
testfunc.argtype = 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".

As a side note the line of code y.Rows[0].Address[0] will trigger an TypeError because of the [0] at the end: 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. Here's some working code:

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

Note: I used Python 2.7.10 on Win10 x64, but nothing here should be Python version or platform specific.

这篇关于Ctypes:将返回的指针映射到结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆