Ctypes:将返回的指针映射到结构 [英] Ctypes: Mapping a returned pointer to a structure
问题描述
我尝试阅读有关此主题的所有问题/答案,但无法进行任何工作。我要做的就是将结构发送到共享库,然后将其返回并可以访问。
我设法创建了一个结构,好了,我可以很好地将其传递给共享库。我知道这一点,因为如果从结构中返回特定值,它将很好地工作。 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
我目前正在尝试一次只发送一个连接器,并返回完全相同的结构。
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屋!