![](/img/trans.png)
[英]How do I get values from a C dll array pointer using ctypes and Python
[英]How do I access wity python ctypes to array values returned with a pointer from a dll coded in Delphi?
我有一個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.
蟒蛇
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.