Jump to content
Sign in to follow this  
hsauro

Returning numpy array constructed in Delphi back to python call

Recommended Posts

I'm using the WrapDelphiClasses unit to construct a Delphi class whose methods than can be called from Python. I have it working without problem for simple types and lists. However, I can't work out how to construct and return a numpy array to the python call. I'm generating data within delphi but I'd like to do some analysis from with Python.

 

I looked at Demo35 and it describes the construction of a numpy array but I am not sure what to return from Delphi.  I am currently testing it with this small test case:

 

function ThostAPI.getNumpy : Variant;
var np: Variant;
     arr: Variant;
begin
  np := Import('numpy');
  arr := np.array(BuiltinModule.range(10));
  result := arr;
end;

 

But when I call this from python it returns None. What is the right way to return a numpy array from Delphi?

 

I'm currently using Delphi 11.3 and the python4delphi that came with getit,. I think however there is a newer version which could be the issue as I know some buffer code has been added.

 

 

 

 

Share this post


Link to post

I updated to the latest 2023 version of delphi4python. It required some changes but it works without issue. The ability to automatically wrap either a class or an instanciated object requires hardly any effort on the Delphi side.

 

I still need to figure out how to return a numpy array from Delphi to python, via a python call at the Python end.

Share this post


Link to post
Posted (edited)

WrapDelphi was designed to expose Delphi classes, records and interfaces to python.   So it did not handle PPyObject parameters or return values.   You could handle that by using the low-level approach (adding an Event to TPythonModule).   However, I have now added to WrapDelphi support for exposing functions with parameters and/or results of type PPyObject.

 

See WrapDelphiTest.pas in the latest version of the pyscripter/python4delphi: Free components that wrap up Python into Delphi and Lazarus (FPC) (github.com) repo.

 

Example:

 

Exposed Method:

function TTestRttiAccess.PlaceInNewList(PyObj: PPyObject): PPyObject;
begin
  with GetPythonEngine do
  begin
    Result := PyList_New(1);
    Py_XIncRef(PyObj);
    PyList_SetItem(Result, 0, PyObj);
  end;
end;

Usage in python

from delphi import rtti_var
list = rtti_var.PlaceInNewList('abc')

The corresponding test in WrapDelphiTest:

procedure TTestWrapDelphi.TestPPyObjects;
var
  List: Variant;
begin
  List := rtti_var.PlaceInNewList('abc');
  Assert.IsTrue(VarIsPythonList(List));
  Assert.AreEqual<string>(List.GetItem(0), 'abc');
end;


 

 

Edited by pyscripter

Share this post


Link to post

Thanks for the reply. I tried a very simple example to try it out with no arguments, a method that just returns a list of NULLs but I'm getting a runtime error (I also used setitem to fill the list in case that was the problem, but same error). This is the method:

 

function ThostAPI.NewList : PPyObject;
begin
    Result := GetPythonEngine.PyList_New(5);
end;

 

and here is the runtime error when using this python code

 

from app import host
x = host.NewList ()
 

TypeError: Call "NewList" returned a value that could not be converted to Python
Error: Unsupported conversion from TValue to Python value

 

I couldn't resolve the issue so I started to use the more low level calls (not using the wrapping unit) and I can return lists and numpy arrays to python. But it would be interesting to know what might be the issue with the above code.  The class that contains NewList is just:

 

{$METHODINFO ON}
  ThostAPI =  class (TPersistent)
      function NewList : PPyObject;
  end;
{$METHODINFO OFF}
 

In the FormCreate I just have:

 

initPython;

 host := THostAPI.Create ();
 DelphiWrapper.RegisterDelphiWrapper(TPyClassWrapper<THostAPI>).Initialize;
 DelphiWrapper.DefineVar('host', host);

Share this post


Link to post
Posted (edited)

I updated the sources yesterday afternoon. I'll take another look at the repo. I see there are some changes from 9 hours ago. I'll update to see if that helps.

Edited by hsauro

Share this post


Link to post

It works!  I can return a numpy array and list easily.

 

Thank you!

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
Sign in to follow this  

×