【问题标题】:Accessing value from callback in ctypes从 ctypes 中的回调访问值
【发布时间】:2013-12-17 17:12:28
【问题描述】:

我正在使用 Python/ctypes 编写基于商业 DLL 的应用程序。此 DLL 读取一个平面文件并通过structs 返回数据。相关的 C structs 如下所示:

struct System{
    unsigned short       user;
    unsigned short       version;
};

struct Message {
    unsigned short       header;
    unsigned short       data;
    unsigned int         messageType;
};

DLL 附带的 API 提供了一个指向具有以下原型的函数的指针。该函数循环遍历平面文件并调用下一个定义的Callback

typedef int (__stdcall *Process) (const char* filename, const char* base, unsigned int flags, int user, Callback stdcallback);

Callback 原型(上面的第五个参数)定义为:

typedef int (__stdcall *Callback) (const System* Sys, const Message* Msg);

在我的python文件中:

from ctypes import *

# using WinDLL for stdcall
lib = WinDLL('CVO.dll')

class System(Structure):
    _fields_ = [('user', c_ushort),
                ('version', c_ushort)]

class Message(Structure):
    _fields_ = [('header', c_ushort),
                ('data', c_ushort),
                ('messageType', c_uint)]

PROTO = WINFUNCTYPE(c_int, POINTER(System), POINTER(Message))

def py_callbck(Sys, Msg):
    print Msg._type_.messageType
    # return 0 to read the next line in the flatfile
    return 0

Callback = PROTO(py_callbck)

pProcess lib.Process
pProcess.argtypes = [c_char_p,c_char_p,c_uint,c_int,PROTO]
pProcess.restype = c_int

pProcess(c_char_p('flat.ccf'),c_char_p(None),c_uint(0),c_int(0),Callback)

我的问题在于访问 DLL 传递给 Msg 结构的值。代码应该打印一个 c_int (0, 1, 2) 而是返回一个 Field 类型,如下所示:

<Field type=c_ulong, ofs=136, size=4>

我知道正在处理平面文件,因为我的 Python 代码打印出数百条 &lt;Field ...&gt; 语句,这是它应该做的。

我的问题是如何访问 DLL 推送到 Msg Structure 而不是返回 &lt;Field ...&gt; 语句的值?

请注意,我对 ctypes 比较陌生,并且 C 语言很少,所以如果您发现定义任何内容有问题,请告诉我。例如,我知道返回对象的ctypes.pointer 和返回新类型的ctypes.POINTER 之间存在区别。当我使用ctypes.pointer 时,代码会出错。

【问题讨论】:

    标签: c++ python c pointers ctypes


    【解决方案1】:

    对于 ctypes 来说相对较新,您在这里做得很好。指针的_type_ 属性是对指向数据类型的引用。在这种情况下,它是Message。类属性messageType 是实例使用的CField 数据描述符。

    您想要做的是取消引用指针以获取Message 实例。您可以使用[0] 下标或contents 属性:

    def py_callbck(Sys, Msg):
        print Msg[0].messageType  # Msg.contents.messageType
        # return 0 to read the next line in the flatfile
        return 0
    

    请记住保留对Callback 的引用,以防止它被垃圾回收。当前,您将其称为全局。没关系。

    关于您调用pProcess 的方式,当您定义argtypes 时,通常不需要手动为简单类型创建ctypes 对象。您可以更简单地使用以下内容:

    pProcess('flat.ccf', None, 0, 0, Callback)
    

    但要注意函数是否需要可写的字符串缓冲区。在这种情况下使用create_string_buffer。这里没有必要,因为char *参数都是const

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 2012-12-14
      • 2019-09-05
      • 2022-07-06
      • 2014-05-13
      • 2013-10-05
      • 1970-01-01
      相关资源
      最近更新 更多