我已经看过其他答案,但似乎无法解决这个问题。我正在尝试在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填充数据数组时为Address,Command和BlockLength设置值。需要此结构的函数将其作为指针
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
open_smbus.restype = c_void_p()
TypeError: restype must be a type, a callable, or None
这是一个工作示例。好像您将错误的类型传递给函数。
#include <stdio.h> #define SMBUS_API __declspec(dllexport) #define SMB_MAX_DATA_SIZE 5 typedef void* SMBUS_HANDLE; typedef struct _SMB_REQUEST { unsigned char Address; unsigned char Command; unsigned char BlockLength; unsigned char Data[SMB_MAX_DATA_SIZE]; } SMB_REQUEST; SMBUS_API int SmBusReadByte(SMBUS_HANDLE handle,SMB_REQUEST *request) { unsigned char i; for(i = 0; i < request->BlockLength; i++) request->Data[i] = i; return request->BlockLength; } SMBUS_API SMBUS_HANDLE OpenSmbus(void) { return (void*)0x12345678; }
from ctypes import * SMB_MAX_DATA_SIZE = 5 ARRAY5 = c_ubyte * SMB_MAX_DATA_SIZE class SMB_REQUEST(Structure): _fields_ = [ ("Address", c_ubyte), ("Command", c_ubyte), ("BlockLength", c_ubyte), ("Data", ARRAY5)] smbus_read_byte = CDLL('x').SmBusReadByte smbus_read_byte.argtypes = [c_void_p,POINTER(SMB_REQUEST)] smbus_read_byte.restype = c_int open_smbus = CDLL('x').OpenSmbus open_smbus.argtypes = [] open_smbus.restype = c_void_p handle = open_smbus() print 'handle = %08Xh' % handle smb_request = SMB_REQUEST(1,2,5) print 'returned =',smbus_read_byte(handle,byref(smb_request)) print 'Address =',smb_request.Address print 'Command =',smb_request.Command print 'BlockLength =',smb_request.BlockLength for i,b in enumerate(smb_request.Data): print 'Data[%d] = %02Xh' % (i,b)
handle = 12345678h returned = 5 Address = 1 Command = 2 BlockLength = 5 Data[0] = 00h Data[1] = 01h Data[2] = 02h Data[3] = 03h Data[4] = 04h