How do I access wity python ctypes to array values returned with a pointer from a dll coded in Delphi?
Question: I have a Delphi library that is exposing a results with a procedure like this:

    
    
    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;
    

And I am able to call it from normal delphi Code like this:

    
    
    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;
    

I would like to wrap the code in Python using the ctypes library and I have
some code like this:

    
    
    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 []
    

But this is not working: I just get the correct BufLen.value but then, with
the second call to dll I am not able to populate my array. I did many similar
tries, but with no luck. Is there someone that can advise me?

Thank you.


Answer: I'd call it like this:

    
    
    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)
    

This function would be much better if you return buffer length rather than
size.

I tested this using the following code:

**Delphi**

    
    
    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
    

**Output**

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

