gpt4 book ai didi

python - 如何使用 python ctypes 访问用 Delphi 编码的 dll 中的指针返回的数组值?

转载 作者:行者123 更新时间:2023-11-28 22:55:10 25 4
gpt4 key购买 nike

我有一个 Delphi 库,它使用如下过程公开结果:

procedure Script_GetFindedList(List : Pointer; out Len : Cardinal); stdcall;
var X : TArray<Cardinal>;
begin
TScriptMethod.Create(SCGetFindedList).SendExecMethod.Free;
NamedPipe.WaitForReply(Pipe_WaitDelay);
if not ResultReady then ExitProcess(0);
SetLength(X,FuncResultStream.Size div 4);
FuncResultStream.Read(X[0],FuncResultStream.Size);
Len := Length(X) * 4;
if Assigned(List) then
Move(X[0],PByteArray(List)^[0],Len);
end;

而且我可以像这样从普通的 delphi 代码中调用它:

function TFindEngine.GetFindedList : TArray<Cardinal>;
var BufLen : Cardinal;
begin
Script_GetFindedList(nil, BufLen);
if BufLen = 0 then Exit;
SetLength(Result,BufLen div 4);
Script_GetFindedList(PByteArray(Result), BufLen);
end;

我想使用 ctypes 库将代码包装在 Python 中,我有一些这样的代码:

from ctypes import *

my_dll = windll.Script

def GetFindedList():
my_dll.Script_GetFindedList.argtypes = [POINTER(c_uint), POINTER(c_uint)]
my_dll.Script_GetFindedList.restype = None

BufLen = c_uint()

my_dll.Script_GetFindedList(None, byref(BufLen))
if BufLen.value > 0:
print("BufLen.value : {}".format(BufLen.value))

##################################################################
# alternate solution that just leaks memory while doing nothind
# buf = array('I', range(BufLen.value))
# addr, count = buf.buffer_info()
# Result = cast(addr, POINTER( (c_uint * BufLen.value) ))

Result = (c_uint * BufLen.value)()

print("Result before: {}".format(list(Result)))

my_dll.Script_GetFindedList(byref(Result), byref(BufLen))
print("Result after: {}".format(list(Result)))

return Result
else:
return []

但这是行不通的:我只是得到了正确的 BufLen.value 但是随后,第二次调用 dll 我无法填充我的数组。我做了很多类似的尝试,但没有运气。有没有人可以给我建议?

谢谢。

最佳答案

我会这样调用它:

from ctypes import *
my_dll = windll.Script
my_dll.Script_GetFindedList.restype = None
size = c_uint()
my_dll.Script_GetFindedList(None, byref(size))
result = (c_uint*(size.value//4))()
my_dll.Script_GetFindedList(result, byref(size))
result = list(result)

如果返回缓冲区长度而不是大小,此函数会好得多。

我使用以下代码对此进行了测试:

德尔福

library TestDLL;

procedure Script_GetFindedList(List : Pointer; out Len : Cardinal); stdcall;
var
X: TArray<Cardinal>;
begin
X := TArray<Cardinal>.Create(1, 2, 3, 4, 5);
Len := Length(X) * 4;
if Assigned(List) then
Move(Pointer(X)^, List^, Len);
end;

exports
Script_GetFindedList;

begin
end.

python

from ctypes import *
my_dll = WinDLL(r'full/path/to/TestDLL.dll')
my_dll.Script_GetFindedList.restype = None
size = c_uint()
my_dll.Script_GetFindedList(None, byref(size))
result = (c_uint*(size.value//4))()
my_dll.Script_GetFindedList(result, byref(size))
result = list(result)
print result

输出

[1L, 2L, 3L, 4L, 5L]

关于python - 如何使用 python ctypes 访问用 Delphi 编码的 dll 中的指针返回的数组值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17308860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com