【问题标题】:Python and WinDLL calling doesn't return from the DLL callPython 和 WinDLL 调用不会从 DLL 调用返回
【发布时间】:2018-11-18 11:00:26
【问题描述】:

我的 DLL 有以下功能:

extern "C" __declspec(dllexport) bool __cdecl  PcapOpen(unsigned long inSize, void * inData, unsigned long *outSize, void * outData, Function_Modes eMode)

函数将通过 outSizeoutData 写出数据(这意味着需要将这些数据传递给函数,并期望我在 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% 清楚如何为这些函数分配数据以使用它们——所以这可能是我的问题

感谢您的协助。

【问题讨论】:

  • 几个(可能是幼稚的)cmets:1.该函数声明为__cdecl,但您在问题标题中提到了WinDLL。您能否编辑您的代码以包含您加载 DLL 的方式(即 pPcapDLL 的来源)? 2.你试过用ctypes.byref(outdata)替换ctypes.byref(outdata_ptr)吗?就目前而言,看起来您的代码正在传递一个指向函数指针的指针,而它似乎只需要一个指针。
  • 我解决了这个问题,我会尝试 outdata_ptr => outdata -> 刚刚尝试过,我收到“ValueError:过程可能调用了太多参数(超过 20 个字节)”

标签: python python-3.x windows dll ctypes


【解决方案1】:

在我看来,您需要进行两项更改:

  1. 您尝试调用的 C 函数使用 cdecl 调用约定,因此您必须使用 ctypes.cdll 而不是 ctypes.windll 访问 DLL。 ctypes.windll 用于 stdcall 调用约定。另请参阅Python ctypes documentation

  2. 您的函数的第四个参数是一个指针,但您似乎将一个指向指针的指针传递给它。尝试将ctypes.byref(outdata_ptr) 替换为ctypes.byref(outdata)

【讨论】:

  • 我会尽力让你知道
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 2023-04-03
  • 2020-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多