2

次のような手順で結果を公開している 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 への 2 回目の呼び出しでは、配列に値を設定できません。私は多くの同様の試みをしましたが、運がありませんでした。私にアドバイスできる人はいますか?

ありがとうございました。

4

1 に答える 1

4

私はそれを次のように呼びます:

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】
于 2013-06-26T06:14:11.423 に答える