我的DLL具有以下功能:
extern "C" __declspec(dllexport) bool __cdecl PcapOpen(unsigned long inSize, void * inData, unsigned long *outSize, void * outData, Function_Modes eMode)
该函数将通过 outSize 和 outData 写出数据(这意味着需要将这些传递给函数,并希望DLL中的函数会对其进行修改)
此外, Function_Modes 是:
typedef enum Function_Modes { Mode_Unknown = -1, Mode_Preview = 0, Mode_Execute = 1, Mode_Query } Function_Modes;
对于Perl的引用,我引用了如下函数:
my %Data;
$Data{Interface} = $interface;
my ($inData, $inSize) = buildData(\%Data);
$$outSize = pack("L", 65536);
$outData = "\x00"x65536;
my $pPcapOpen = Win32::API->new($dllName, "PcapOpen", "NPPPI", "I", "_cdecl");
my $return = $pPcapOpen->Call($inSize, $inData, $$outSize, $outData, $eMode);
我创建了一个小的Python代码,该代码应运行该函数并显示其返回的数据,但是在“似乎访问DLL”时调用不会返回(永远不会调用该调用之后的python代码)>
pPcapDLL = ctypes.WinDLL("Pcap Interface.dll")
LP_c_char = ctypes.POINTER(ctypes.create_string_buffer(65536).__class__)
obuf = ctypes.create_string_buffer(65536)
obuflen = ctypes.c_ulong(65536)
optr = LP_c_char(obuf)
PcapOpen = pPcapDLL["PcapOpen"]
PcapOpen.restype = ctypes.c_bool
PcapOpen.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.POINTER(LP_c_char), ctypes.POINTER(ctypes.c_size_t), ctypes.c_int]
outSize = ctypes.c_ulong(65536)
LP_c_char = ctypes.POINTER(ctypes.create_string_buffer(65536).__class__)
outData = ctypes.create_string_buffer(65536)
outData_ptr = LP_c_char(outData)
print("Calling PcapClose")
returnValue = PcapClose(inSize, inData, ctypes.byref(outSize), ctypes.byref(outData_ptr), eMode)
print("returnValue: {}".format(returnValue)) # <-- This doesn't get called
关于如何处理返回数据的DLL函数的文件似乎很少,应该使用byref,但是并不能100%清楚如何为这些函数分配数据以使用它们-所以这可能是我的问题
感谢您的协助。
答案 0 :(得分:1)
如我所见,您需要进行两项更改:
您尝试调用的C函数使用cdecl
调用约定,因此您必须使用ctypes.cdll
而不是ctypes.windll
访问DLL。 ctypes.windll
用于stdcall
调用约定。另请参见Python ctypes
documentation。
函数的第四个参数是指针,但是您似乎正在将其传递给指针。尝试将ctypes.byref(outdata_ptr)
替换为ctypes.byref(outdata)
。