Want to build a Delphi/C++ builder Application that should exchange values between Delphi and Python Objects. Not sure how to do it? Python4Delphi has two powerful components to achieve this faster, you can use either one component for your application. In this post, we can see both ways.
- Python4Delphi Demo16 Example1 App shows how to assign a variable value between Delphi and Python using the TPythonDelphiVar component events. This can be achieved by events that set and gets data as a python object. Internally this component converts a value from Delphi to python and vice versa. You can find the Demo16 Example1 source on GitHub.
- Python4Delphi Demo16 Example2 App shows how to assign a variable value between Delphi and Python using TPythonModule, create a module, add few routines to that module, Import the module in a python script, and access the added routine. You can find the Demo16 Example2 source on GitHub.
Prerequisites: Download and install the latest Python for your platform. Follow the Python4Delphi installation instructions mentioned here. Alternatively, you can check out this video Getting started with Python4Delphi.
Components used in Python4Delphi Demo16 App:
- TPythonEngine: A collection of relatively low-level routines for communicating with Python, creating Python types in Delphi, etc. It’s a singleton class.
- TPythonGUIInputOutput: Inherited from TPythonInputOutput (which works as a console for python outputs) Using this component Output property you can associate the Memo component to show the Output.
- TMemo: A multiline text editing control, providing text scrolling. The text in the memo control can be edited as a whole or line by line.
Example1: TPythonDelphiVar Inherited from TEngineClient, used to convert the python variable to the Delphi variable and vice versa. It has methods to set and get value as variant or PyObject. It contains property like Module(TPythonModule internally created by default) where the python variable(TPyVar) is created and later converted to and from the Delphi variant or PyObject.
You can find the Python4Delphi Demo16a sample project from the extracted repository ..Python4DelphiDemosDemo16Example1Demo16a.dproj. Open this project in RAD Studio 10.4.1 and run the application.
Implementation Details:
- PythonEngine1 provides the connection to Python or rather the Python API. This project uses Python3.9 which can be seen in TPythonEngine DllName property. It Is assigned with InitScript which import sys module and prints the Python.Dll version, copyright information to Memo2. import sys print(“Python Dll: “, sys.version) print(sys.copyright) print()
- PythonGUIInputOutput1 provides a conduit for routing input and output between the Graphical User Interface (GUI) and the currently executing Python script.
- PythonDelphiVar1 component is intended for demonstrating how to assign value between Delphi components( like edit box, check box and group boxes) ->Python Delphi variable(Properties.Value) and back from (Properties.Value) -> Delphi components( like edit box, check box and group boxes) using event PythonDelphiVar1ExtGetData and PythonDelphiVar1ExtSetData respectively. The data is passed as Python Dictionary Type Object here. The CreateProperties and UpdateProperties routine creates a python dictionary object and Updates the python dictionary object when the value is changed in the UI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
procedure TForm1.PythonDelphiVar1ExtGetData(Sender: TObject; var Data: PPyObject); begin with GetPythonEngine do begin // Return our object Data := FProperties; // Don't forget to increment it, otherwise we would loose property ! Py_XIncRef(Data); end; end; procedure TForm1.PythonDelphiVar1ExtSetData(Sender: TObject; Data: PPyObject); begin with GetPythonEngine do begin // Check if the transmitted object is a dictionary if not PyDict_Check(Data) then Exit; // Acquire property to the transmitted object Py_XIncRef(Data); // Release property of our previous object Py_XDecRef(FProperties); // Assisgn transmitted object FProperties := Data; end; end; |
- Memo1, used for providing the Python Script to execute, and Memo2 for showing the output.
- On Clicking Execute Button the python script is executed.
Example2: TPythonModule inherited from TMethodsContainer class allows creating modules by providing a name. You can use routines AddDelphiMethod, AddDelphiMethodWithKW to add a method of type PyCFunction. You can create events using the Events property.
You can find the Python4Delphi Demo16b sample project from the extracted repository ..Python4DelphiDemosDemo16Example2Demo16b.dproj. Open this project in RAD Studio 10.4.1 and run the application.
Implementation Details:
- PythonEngine1 provides the connection to Python or rather the Python API. This project uses Python3.9 which can be seen in TPythonEngine DllName property.
- PythonGUIInputOutput1 provides a conduit for routing input and output between the Graphical User Interface (GUI) and the currently executing Python script.
- PythonModule1 with Module name props is created. During PythonModule1Initialization a three DelphiMethods(GetProperty,SetProperty,GetPropertyList) are added to the Module. Logically a python module is created and its methods were created using this PythonModule. Later this can be imported into your python script wherever necessary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
function TForm1.GetProperty(pSelf, Args : PPyObject) : PPyObject; cdecl; var key : PAnsiChar; begin with GetPythonEngine do if PyArg_ParseTuple( args, 's:GetProperty',@key ) <> 0 then begin if key = 'Title' then Result := VariantAsPyObject(cbTitle.Text) else if key = 'Name' then Result := VariantAsPyObject(edName.Text) else if key = 'Informatician' then Result := VariantAsPyObject(cbInformatician.Checked) else if key = 'PythonUser' then Result := VariantAsPyObject(cbPythonUser.Checked) else if key = 'Age' then Result := VariantAsPyObject(edAge.Text) else if key = 'Sex' then Result := VariantAsPyObject(rgSex.ItemIndex) else begin PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Format('Unknown property "%s"', [key]))); Result := nil; end; end else Result := nil; end; function TForm1.SetProperty(pSelf, Args : PPyObject) : PPyObject; cdecl; var key : PAnsiChar; value : PPyObject; begin with GetPythonEngine do if PyArg_ParseTuple( args, 'sO:SetProperty',@key, @value ) <> 0 then begin if key = 'Title' then begin cbTitle.Text := PyObjectAsVariant( value ); Result := ReturnNone; end else if key = 'Name' then begin edName.Text := PyObjectAsVariant( value ); Result := ReturnNone; end else if key = 'Informatician' then begin cbInformatician.Checked := PyObjectAsVariant( value ); Result := ReturnNone; end else if key = 'PythonUser' then begin cbPythonUser.Checked := PyObjectAsVariant( value ); Result := ReturnNone; end else if key = 'Age' then begin edAge.Text := PyObjectAsVariant( value ); Result := ReturnNone; end else if key = 'Sex' then begin rgSex.ItemIndex := PyObjectAsVariant( value ); Result := ReturnNone; end else begin PyErr_SetString (PyExc_AttributeError^, PAnsiChar(Format('Unknown property "%s"', [key]))); Result := nil; end; end else Result := nil; end; |
- Memo1, used for providing the Python Script to execute, and Memo2 for showing the output.
- On Clicking Execute Button the python script is executed.
Head over and check out the Python4Delphi project to easily build Python GUIs for Windows.