Python 3 使用自定义数据类型调用外部 DLL
Python 3 calling external DLL with custom data type
我正在尝试使用 C 中的以下 header 定义调用外部 DLL。
typedef long EPC_INT32;
typedef void* EPC_ADDR32;
typedef struct {EPC_CHAR a [16];} EPC_Str16;
typedef struct
{
EPC_INT32 UseUSB;
EPC_INT32 BoardNumber;
EPC_INT32 FIFOSamples;
EPC_INT32 MaxProbes;
EPC_Str16 DeviceNumber;
EPC_Str16 SerialNumber;
EPC_INT32 ExternalScaling;
EPC_ADDR32 DacScaling;
EPC_ADDR32 AdcScaling;
} LIH_OptionsType;
typedef LIH_OptionsType* LIH_OptionsPtr;
EPC_INT32 EPC_Calling LIH_InitializeInterface(
EPC_Str256Ptr ErrorMessage,
EPC_INT32 Amplifier,
EPC_INT32 ADBoard,
LIH_OptionsPtr OptionsPtr,
EPC_INT32 OptionsSize ) EPC_Import;
Python代码:
import ctypes
import sys
class LIH_Options(ctypes.Structure):
_fields_ = [("UseUSB", ctypes.c_int32) ,
("BoardNumber", ctypes.c_int32),
("FIFOSamples", ctypes.c_int32),
("MaxProbes", ctypes.c_int32),
("DeviceNumber", ctypes.c_wchar_p),
("SerialNumber", ctypes.c_wchar_p),
("ExternalScaling", ctypes.c_int32),
("DataScaling", ctypes.c_void_p),
("AdcScaling", ctypes.c_void_p)]
OptionsSize = sys.getsizeof(LIH_Options)
my_LIH_Options = LIH_Options(0,0,1024,0,'','',0, 0,0) #create an instance
EPC = ctypes.WinDLL('EpcDLL.dll')
EPC.LIH_InitializeInterface.argtypes = [ctypes.c_char_p,
ctypes.c_int32, ctypes.c_int32,
ctypes.POINTER(LIH_Options),
ctypes.c_int32]
szErrMssg = ctypes.create_string_buffer(256)
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, my_LIH_Options, OptionsSize)
这个 returns 一个 Tracback 错误:
status = EPC.LIH_InitializeInterface(szErrMssg, 0, int(LIH.Board), my_LIH_Options, OptionsSize)
OSError:异常:访问冲突写入 0xFFFFFFFF
如果调用被替换为
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, None, OptionsSize)
它可以工作,使用 LIH_Options 的默认值。所以问题在于传递数据类型 LIH_Options.
结构的数组类型和大小不正确。这应该可行,但未经测试,因为我没有您的 DLL。 None
通常用于 NULL 指针,但 0 也应该有效。对 char
数组使用字节字符串 (b''
)。
import ctypes
# define the types for easier match to original C structure.
EPC_INT32 = ctypes.c_int32;
EPC_ADDR32 = ctypes.c_void_p; # Only 32-bit on a 32-bit OS.
EPC_CHAR = ctypes.c_char; # Assumption...not defined in question
EPC_Str16 = EPC_CHAR * 16; # Correct type of char[16] array
class LIH_Options(ctypes.Structure):
_fields_ = [("UseUSB", EPC_INT32),
("BoardNumber", EPC_INT32),
("FIFOSamples", EPC_INT32),
("MaxProbes", EPC_INT32),
("DeviceNumber", EPC_Str16),
("SerialNumber", EPC_Str16),
("ExternalScaling", EPC_INT32),
("DataScaling", EPC_ADDR32),
("AdcScaling", EPC_ADDR32)]
OptionsSize = ctypes.sizeof(LIH_Options) # sys.getsizeof returns size of Python object, not C
my_LIH_Options = LIH_Options(0,0,1024,0,b'',b'',0,None,None) #create an instance
EPC = ctypes.WinDLL('EpcDLL.dll')
EPC.LIH_InitializeInterface.argtypes = [ctypes.c_char_p,
EPC_INT32, EPC_INT32,
ctypes.POINTER(LIH_Options),
EPC_INT32]
szErrMssg = ctypes.create_string_buffer(256)
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, my_LIH_Options, OptionsSize)
我正在尝试使用 C 中的以下 header 定义调用外部 DLL。
typedef long EPC_INT32;
typedef void* EPC_ADDR32;
typedef struct {EPC_CHAR a [16];} EPC_Str16;
typedef struct
{
EPC_INT32 UseUSB;
EPC_INT32 BoardNumber;
EPC_INT32 FIFOSamples;
EPC_INT32 MaxProbes;
EPC_Str16 DeviceNumber;
EPC_Str16 SerialNumber;
EPC_INT32 ExternalScaling;
EPC_ADDR32 DacScaling;
EPC_ADDR32 AdcScaling;
} LIH_OptionsType;
typedef LIH_OptionsType* LIH_OptionsPtr;
EPC_INT32 EPC_Calling LIH_InitializeInterface(
EPC_Str256Ptr ErrorMessage,
EPC_INT32 Amplifier,
EPC_INT32 ADBoard,
LIH_OptionsPtr OptionsPtr,
EPC_INT32 OptionsSize ) EPC_Import;
Python代码:
import ctypes
import sys
class LIH_Options(ctypes.Structure):
_fields_ = [("UseUSB", ctypes.c_int32) ,
("BoardNumber", ctypes.c_int32),
("FIFOSamples", ctypes.c_int32),
("MaxProbes", ctypes.c_int32),
("DeviceNumber", ctypes.c_wchar_p),
("SerialNumber", ctypes.c_wchar_p),
("ExternalScaling", ctypes.c_int32),
("DataScaling", ctypes.c_void_p),
("AdcScaling", ctypes.c_void_p)]
OptionsSize = sys.getsizeof(LIH_Options)
my_LIH_Options = LIH_Options(0,0,1024,0,'','',0, 0,0) #create an instance
EPC = ctypes.WinDLL('EpcDLL.dll')
EPC.LIH_InitializeInterface.argtypes = [ctypes.c_char_p,
ctypes.c_int32, ctypes.c_int32,
ctypes.POINTER(LIH_Options),
ctypes.c_int32]
szErrMssg = ctypes.create_string_buffer(256)
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, my_LIH_Options, OptionsSize)
这个 returns 一个 Tracback 错误: status = EPC.LIH_InitializeInterface(szErrMssg, 0, int(LIH.Board), my_LIH_Options, OptionsSize) OSError:异常:访问冲突写入 0xFFFFFFFF
如果调用被替换为
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, None, OptionsSize)
它可以工作,使用 LIH_Options 的默认值。所以问题在于传递数据类型 LIH_Options.
结构的数组类型和大小不正确。这应该可行,但未经测试,因为我没有您的 DLL。 None
通常用于 NULL 指针,但 0 也应该有效。对 char
数组使用字节字符串 (b''
)。
import ctypes
# define the types for easier match to original C structure.
EPC_INT32 = ctypes.c_int32;
EPC_ADDR32 = ctypes.c_void_p; # Only 32-bit on a 32-bit OS.
EPC_CHAR = ctypes.c_char; # Assumption...not defined in question
EPC_Str16 = EPC_CHAR * 16; # Correct type of char[16] array
class LIH_Options(ctypes.Structure):
_fields_ = [("UseUSB", EPC_INT32),
("BoardNumber", EPC_INT32),
("FIFOSamples", EPC_INT32),
("MaxProbes", EPC_INT32),
("DeviceNumber", EPC_Str16),
("SerialNumber", EPC_Str16),
("ExternalScaling", EPC_INT32),
("DataScaling", EPC_ADDR32),
("AdcScaling", EPC_ADDR32)]
OptionsSize = ctypes.sizeof(LIH_Options) # sys.getsizeof returns size of Python object, not C
my_LIH_Options = LIH_Options(0,0,1024,0,b'',b'',0,None,None) #create an instance
EPC = ctypes.WinDLL('EpcDLL.dll')
EPC.LIH_InitializeInterface.argtypes = [ctypes.c_char_p,
EPC_INT32, EPC_INT32,
ctypes.POINTER(LIH_Options),
EPC_INT32]
szErrMssg = ctypes.create_string_buffer(256)
status = EPC.LIH_InitializeInterface(szErrMssg, 0, 3, my_LIH_Options, OptionsSize)