Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ctypes不';t正确返回通过引用传递的某些值_Python_Ctypes - Fatal编程技术网

Python ctypes不';t正确返回通过引用传递的某些值

Python ctypes不';t正确返回通过引用传递的某些值,python,ctypes,Python,Ctypes,我正在尝试从Python调用DLL。DLL是用C语言编写的,没有什么特别复杂的地方。这正是ctypes的用途。但是,我在从DLL函数调用返回的结构中获取正确的值时遇到困难。传递的结构中的第一个值返回正确,但其他值返回错误 代码从内存中的缓冲区读取多条消息。它使用ReadFirst()/ReadNext()编码范式。有一个“当前消息”结构被传入以跟踪状态 下面是保存当前ReadFirst()/ReadNext()状态的C结构 这是用ctypes编写的ctypes结构副本 class CurrMsg

我正在尝试从Python调用DLL。DLL是用C语言编写的,没有什么特别复杂的地方。这正是ctypes的用途。但是,我在从DLL函数调用返回的结构中获取正确的值时遇到困难。传递的结构中的第一个值返回正确,但其他值返回错误

代码从内存中的缓冲区读取多条消息。它使用ReadFirst()/ReadNext()编码范式。有一个“当前消息”结构被传入以跟踪状态

下面是保存当前ReadFirst()/ReadNext()状态的C结构

这是用ctypes编写的ctypes结构副本

class CurrMsg_1553F1(ctypes.Structure):
    ''' Data structure for the current 1553 message info structure '''
    _pack_   = 1
    _fields_ = [("MsgNum",      ctypes.c_uint32),
                ("CurrOffset",  ctypes.c_uint32),
                ("DataLen",     ctypes.c_uint32),
                ("pChanSpec",   ctypes.POINTER(ChanSpec_1553F1)),
                ("p1553Hdr",    ctypes.c_void_p),
                ("pCmdWord1",   ctypes.POINTER(CmdWord)),
                ("pCmdWord2",   ctypes.POINTER(CmdWord)),
                ("pStatWord1",  ctypes.c_void_p),
                ("pStatWord2",  ctypes.c_void_p),
                ("WordCnt",     ctypes.c_uint16),
                ("pData",       ctypes.c_void_p)]
我将在下面提供更多细节,但问题的关键是对ReadFirst()/ReadNext()的调用正确地返回MsgNum的值,而其他值是垃圾。这是一个示例输出

MsgNum 0  CurrOffset 40912728  DataLen 40912732  Messages = 3664897
MsgNum 1  CurrOffset 40912728  DataLen 40912748  Messages = 60417
MsgNum 2  CurrOffset 40912728  DataLen 40912748  Messages = 60417
etc.
MsgNum是正确的,ReadFirst()/ReadNext()的迭代次数正确。但是,CurrOffset和DataLen的值是垃圾。(Messages值已从指向其他内存的指针中取消引用。我认为我还没有正确的设置,但在修复其他内容之前,我必须保存该值。如果CurrOffset和DataLen错误,则指向pChanSpec的指针也可能错误。)

以下是函数的接口

EnI106Status enI106_Decode_First1553F1
    (SuI106Ch10Header * psuHeader,
     void             * pvBuff,
     Su1553F1_CurrMsg * psuMsg);

EnI106Status enI106_Decode_Next1553F1
    (Su1553F1_CurrMsg * psuMsg);
这些DLL函数(连同调试打印语句)由

C DLL是在Visual Studio 2005下编译的。在很多C++和C++.NET程序中,我都使用过这个DLL,没有任何问题。p> 我在其他代码中使用了ctypes和structs来返回值,它似乎工作得很好。由于结构中的第一个值是可以的,但后续值与此“感觉”相差甚远,这就像是一个数据对齐问题。我在ctypes结构中设置了pack=1,并在编译的DLL代码中设置了字节对齐。我已经对每个结构的打印输出进行了大小测试,并验证它们是否为预期大小


我已经在这件事上撞了一阵子了,我已经没有主意了。关于下一步尝试什么有什么想法吗?

我注意到C结构的第一个元素是unsigned int,但是您的python结构是C_uint32。你确定它们在你的架构上大小相同吗

如果这没有任何帮助,我将执行以下操作来追踪问题的根源:

首先,我将从python声明中删除
\upack
,并从C源代码中删除任何
\pragma pack
或其他对齐操作。从已知位置开始,即本机对齐

然后

我将编写一个C程序来迭代该结构,并使用
offsetof(struct,field)
打印每个成员的偏移量。此外,这个程序应该调用First()和少量调用Next(),并将结构以二进制形式写入文件

接下来,使用struct模块编写一个python脚本,在从C程序编写的结构上迭代,并利用字段大小和对齐的知识调用(…)以查找正确定义结构的格式字符串


有了这些知识,您应该能够在Python代码中正确地编码ctypes.Structure

,您可以传递byref(self.CurrMsg),但可以打印Decode1553.CurrMsg中的字段。您不应该从self.CurrMsg打印字段吗?
EnI106Status enI106_Decode_First1553F1
    (SuI106Ch10Header * psuHeader,
     void             * pvBuff,
     Su1553F1_CurrMsg * psuMsg);

EnI106Status enI106_Decode_Next1553F1
    (Su1553F1_CurrMsg * psuMsg);
def __init__(self, PacketIO):
    self.CurrMsg  = CurrMsg_1553F1()

def Decode_First1553F1(self):
    Status = self.PacketIO._IrigDataDll.enI106_Decode_First1553F1(ctypes.byref(self.PacketIO.Header), ctypes.byref(self.PacketIO.Buffer),  ctypes.byref(self.CurrMsg))
    print "MsgNum %d  CurrOffset %d  DataLen %d  Messages = %d" % \
        (Decode1553.CurrMsg.MsgNum, Decode1553.CurrMsg.CurrOffset, Decode1553.CurrMsg.DataLen, Decode1553.CurrMsg.pChanSpec.contents.MsgCnt)
    return Status

def Decode_Next1553F1(self):
    Status = self.PacketIO._IrigDataDll.enI106_Decode_Next1553F1(ctypes.byref(self.CurrMsg))
    print "MsgNum %d  CurrOffset %d  DataLen %d  Messages = %d" % \
        (Decode1553.CurrMsg.MsgNum, Decode1553.CurrMsg.CurrOffset, Decode1553.CurrMsg.DataLen, Decode1553.CurrMsg.pChanSpec.contents.MsgCnt)
    return Status