Jump to content
BennieC

Returning lists from Python to Delphi

Recommended Posts

Hi,

I have a Delphi application and am calling some Python functions from it.  The function in Python returns a set of lists.  How do I write Delphi code to receive these lists.

 

Return statement in Python:

    return lboxes, lidxs, lconfidences
 

In Delphi I have used single value returns but now need to receive three distinct lists..

 

Any suggestions or assistance

Share this post


Link to post

Thank you.  Of course my problem is that Delphi does not support tuples.  How can I create variables in Delphi to return results into.

Share this post


Link to post

You can use either VarPy or the low-level python API to manipulate python tuples (e.g PyTuple_GetItem, PyTuple_SetItem etc.)

 

with VarPyth the unit tests give you a good idea of things you can do:

 

  c := VarPythonCreate([1, 2, 3, 4], stTuple); // test a tuple
  Assert.IsTrue( VarIsPythonTuple(c) );
  Assert.IsTrue( VarIsPythonSequence(c) );
  Assert.IsTrue( c.GetItem(1) = 2 );
  Assert.IsTrue( c.Length = 4 );
  c := NewPythonTuple(3);
  c.SetItem(0, 1);
  c.SetItem(1, 2);
  c.SetItem(2, 3);
  Assert.IsTrue( VarIsPythonTuple(c) );
  Assert.IsTrue( VarIsPythonSequence(c) );
  Assert.IsTrue( c.GetItem(1) = 2 );
  Assert.IsTrue( c.Length = 3 );

from python4delphi/VarPythTest.pas at master · pyscripter/python4delphi (github.com) 

 

Share this post


Link to post

Thanks a lot - I am progressing.

I now have a next problem in getting a list

 

Python Code

import P4D_P5_Python as md
from myPyMod import np_array

myboxes = []
myboxes = md.CreateArray()    THIS JUST CREATES AN ARRAY OF RECTANGLES [t, l, w, h]
 

Delphi Code

  PythonEngine1.ExecStrings(mePyInit.Lines);            // This creates and runs the Python code

 

FIRST ATTEMPT

  // Sien Demo 17

  myV := PythonModule1.GetVarAsVariant('myboxes');   THIS FAILS WITH ACCESS VIOLATION
 

SECOND ATTEMPT

 // From P4D tutorial 2
  for var V in VarPyIterate(MainModule.myboxes) do      THIS WORKS BUT VALUES V ARE STRINGS
  begin
  // If arrays are rectangles
    assert( varispythonlist(V));
    Vlength := length(V);
    Listbox1.Items.Add('len(V) = ' + inttostr(Vlength));
    Listbox1.items.add(V);
  end;
 

 

ANy suggestions on where I am going wrong

Share this post


Link to post

  for var V in VarPyIterate(MainModule.myboxes) do

 

V will be a python variant pointing to whatever is inside myboxes.

 

  Listbox1.items.add(V);

 

The above converts the python variant to string.

Edited by pyscripter

Share this post


Link to post

Thank you

I gathered that, but when I use my first attempt: GetVarAsVariant it fails with ACCESS VIOLATION

I still struggle to see how Delphi can convert a python variant to the required format.  Must I first declare the structure in Delphi?  What if I don't know the structure?

I have attached my test program in which I am trying to understand the principles - maybe you can understand my problem better in this.

In the long run I will have to deal with quite complex tuples from my Yolo ML project (Which currently runs in C#) but I need to understand the principles first.

Regards

prjP4D_P5_VarPyth.zip

Share this post


Link to post

I have found the offending code in PythonEngine - function PyObjectAsVariant

In line 5390 there is an ExtractDate(Result) line.  Following thorugh it goes to the ExtractDate function with an unassigned value for date, but expecting to decode obj which is nil at this point - hence the error.  This is nil because Getvar in GetVarAsVariant returned a nil for obj.

Now clearly my Python object has a value as it returns it as strings in the VarPyIterate function.

 

Can this help to explain my problem?

Regards

Share this post


Link to post

I am not sure what is the problem you are trying to solve.

 

Your "Second attempt" should work.

In your "First attempt"

 

 myV := PythonModule1.GetVarAsVariant('myboxes');

 

fails because PythonModule1 has no variable 'myboxes'.   myboxes will be part of the main module namespace after your code gets executed.

 

GetVarAsVariant can be improved to avoid the access violation.

function  TPythonModule.GetVarAsVariant( const varName : AnsiString ) : Variant;
var
  obj : PPyObject;
begin
  CheckEngine;
  with Engine do
    begin
      obj := GetVar( varName );
      if Assigned(obj) then
        try
          Result := PyObjectAsVariant( obj );
        finally
          Py_XDecRef(obj);
        end;
    end;
end;

 

Edited by pyscripter

Share this post


Link to post

I am still struggling with getting my results into Delphi.  I have used direct access to the Python function as shown in the screencopy and in fact receive the correct results in Delphi using Code insight as shown.  But I have no success in actually accessing this tuple from Delphi

image.thumb.png.d17ceb8c99d1f4d7aaafe4b01789a76d.png

There are three items in the tuple, the first containing a list of arrays, the second an array and the third a list of values.

How do I individually access these values - some sample code will help as I can't find anything in the demos and my knowledge of variants still seem to be inadequate.

Kind regards

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×