Disons que j'ai cette fonction dans une DLL

function test_3(sInput, sOutput : PChar; sSize : int64): Integer; stdcall;
var
  sTmp : string;
  fText : TextFile;
begin
  sTmp := '+++ ' + sInput + ' +++';
  StrPLCopy(sOutput, PChar(sTmp), sSize);
  Result := 69;
  AssignFile(fText, 'test.txt');
  Rewrite(fText);
  Writeln(fText, 'in: ' + sInput);
  Writeln(fText, 'out: '  + sOutput);
  CloseFile(fText);
end;

Dans mon programme Delphi, je l'appelle comme ceci

…
  Input := EdtIn.Text;
  OutputSize := Input.Length + 8;
  Output := AllocMem(OutputSize);
  RC := test_3(PChar(Input), Output, OutputSize);
  EdtOut.Text := Output;
  FreeMem(Output);

Et ça marche plutôt bien. Maintenant, je veux appeler la fonction à partir d'un script Python.

  import ctypes as ct
  ...
  myString = "test Delphi 10.3 DLL"
  outputsize = len(myString) + 8
  …
  test_3 = lib.test_3
  test_3.restype = ct.c_int
  test_3.argtypes = [ct.c_wchar_p, ct.c_wchar_p]
  sOutput = ct.create_string_buffer(outputsize)
  print("sOutput = " + sOutput.value)

Et je reçois une erreur

ctypes.ArgumentError : argument 2 : : type incorrect

Ma question est donc : quel est l'équivalent Python d'AllocMem en Delphi. Je dois préciser que, bien sûr tout le code est par exemple et dans la "vraie vie" je n'ai pas accès au code Delphi en DLL.

-1
Jean-Philippe 25 févr. 2020 à 12:48

1 réponse

Meilleure réponse

Voici un exemple simple et complet démontrant comment procéder :

Bibliothèque Delphi

library SO_60391682;

uses
  SysUtils;

function testStringOut(Input, Output: PChar; OutputLen: Int64): Integer; stdcall;
var
  tmp: string;
begin
  tmp := '+++ ' + Input + ' +++';
  StrPLCopy(Output, PChar(tmp), OutputLen - 1); 
  // -1 because of StrPLCopy's handling of null terminator
  Result := 0;
end;

exports
  testStringOut;

begin
end.

Programme Python pour appeler la bibliothèque Delphi

import ctypes

lib = ctypes.WinDLL(r'SO_60391682.dll')
testStringOut = lib.testStringOut
testStringOut.restype = ctypes.c_int
testStringOut.argtypes = ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_int64

output = ctypes.create_unicode_buffer(256)
res = testStringOut('foo', output, len(output))
print('res={}, output={}'.format(res, output.value))
2
David Heffernan 26 févr. 2020 à 09:03