【发布时间】:2011-05-20 02:23:05
【问题描述】:
我查看了其他答案,但似乎无法让它发挥作用。我试图在 DLL 中调用一个函数来与 SMBus 设备进行通信。此函数接受一个指向结构的指针,该结构具有一个数组作为其字段之一。所以...
在 C 中:
typedef struct _SMB_REQUEST
{
unsigned char Address;
unsigned char Command;
unsigned char BlockLength;
unsigned char Data[SMB_MAX_DATA_SIZE];
} SMB_REQUEST;
我想我必须在 DLL 填充数据数组时设置地址、命令和块长度的值。 需要这个结构的函数把它当作一个指针
SMBUS_API int SmBusReadByte( SMBUS_HANDLE handle, SMB_REQUEST *request );
所以我在 Python 中设置了这样的结构:
class SMB_REQUEST(ctypes.Structure):
_fields_ = [("Address", c_char),
("Command", c_char),
("BlockLength", c_char),
("Data", type(create_string_buffer(SMB_MAX_DATA_SIZE))]
*注意:我也尝试过 ctypes.c_char*SMB_MAX_DATA_SIZE 作为数据类型*
要将指向这种类型的结构的指针传递给函数,我首先尝试将其初始化如下:
data = create_string_buffer(SMB_MAX_DATA_SIZE)
smb_request = SMB_REQUEST('\x53', \x00', 1, data)
这会响应:
TypeError: expected string or Unicode object, c_char_Array_32 found
如果我尝试省略数据数组,如下所示:
smb_request = SMB_REQUEST('\x53', \x00', 1)
不,错误。 但是,当我尝试将其传递给函数时:
int_response = smbus_read_byte(smbus_handle, smb_request))
我明白了:
ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected LP_SMB_REQUES
T instance instead of SMB_REQUEST
我尝试将它作为指针传递:
int_response = smbus_read_byte(smbus_handle, ctypes.POINTER(smb_request))
我得到:
----> 1
2
3
4
5
TypeError: must be a ctypes type
这是我设置艺术类型的方式:
smbus_read_byte.argtypes = (ctypes.c_void_p, ctypes.POINTER(SMB_REQUEST))
我试过投射,但还是不行。谁能帮我解释一下?
更新:
如果我首先像这样初始化结构:
smb_request = SMB_REQUEST('\xA6', '\x00', chr(1), 'a test string')
然后是参考低音:
int_response = smbus_receive_byte(smbus_handle, ctypes.byref(smb_request))
我没有错误。但是,当函数应该返回“0”表示成功并且返回非零表示失败时,该函数会返回 -1。检查 smb_request.Data 的值会返回“测试字符串”,因此那里没有变化。 任何关于这里可能发生的事情的建议将不胜感激。
谢谢
更新:
由于我收到了一些关于我的手柄是否正确的询问,这就是我的使用方法。 DLL 的头文件声明如下:
typedef void *SMBUS_HANDLE;
//
// This function call initializes the SMBus, opens the driver and
// allocates the resources associated with the SMBus.
// All SMBus API calls are valid
// after making this call except to re-open the SMBus.
//
SMBUS_API SMBUS_HANDLE OpenSmbus(void);
这就是我在 python 中的做法:
smbus_handle = c_void_p() # NOTE: I have also tried it without this line but same result
open_smbus = CDLL('smbus.dll').OpenSmbus
smbus_handle = open_smbus()
print 'SMBUS_API SMBUS_HANDLE OpenSmbus(void): ' + str(smbus_handle)
我在调用 smbus_read_byte() 之前调用它。我尝试设置open_smbus.restype = c_void_p(),但出现错误:TypeError: restype must be a type, a callable, or None
【问题讨论】:
-
嗨马克/亚当,很抱歉延迟回复您的有用答案。我终于拿到了一个逻辑分析仪,可以看到 DLL 的行为与预期不同。在你们给我的帮助下,我现在有了代码。我对 SO 很陌生,我知道不检查正确答案是不礼貌的,但我想将你的两个答案都标记为正确,因为你们都付出了很多努力来帮助我,而且你的代码现在可以工作了。我似乎只能将一个答案标记为正确。你会建议我做什么?
-
附注非常感谢所有的帮助!
-
嘿没问题。很高兴你想出来了。不幸的是,您只能投票给一个。这是你的电话。您也可以随时对两者都投赞成票;^)
标签: python pointers struct ctypes