Earlier we have learned how to create a Python Type using Python4Delphi components in a Delphi GUI app. From the post we know, how to create and use Python4Delphi components such as TPythonEngine, TPythonModule, TPythonType by a simple drag and drop in our application. But sometimes developers may need to instantiate those components dynamically rather than using GUI components. How to do that? This post will guide you to understand better. You can also use Python4Delphi with C++Builder.
Python4Delphi Demo34 Sample App shows how to create, destroy, recreate PythonEngine, and other Python4Delphi components in a Delphi application. You can find the Demo34 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 created Dynamically in Python4Delphi Demo34 Sample App:
- TPythonEngine: A collection of relatively low-level routines for communicating with Python, creating Python types in Delphi, etc. It’s a singleton class.
- TPythonModule: It’s inherited from TMethodsContainer class allows creating modules by providing a name. You can use routines AddMethod, AddMethodWithKW, AddDelphiMethod, AddDelphiMethodWithKeywords to add a method which should be type compatible with this routine parameter. You can create events using the Events property.
- TPythonType: This component helps to create a new python type in Delphi which is inherited from the hierarchy of classes (set of APIs to create, manage methods, and members).
Components created in Python4Delphi Demo34 Sample App using GUI:
- 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.
- TComboBox to list the Registered Python versions.
You can find the Python4Delphi Demo34 sample project from the extracted repository ..Python4DelphiDemosDemo34.dproj. Open this project in RAD Studio 10.4.1 and run the application.
Implementation Details:
- PythonGUIInputOutput1 provides a conduit for routing input and output between the Graphical User Interface (GUI) and the currently
executing Python script. - To retrieve the registered Python Versions, it uses unit PythonVersions routine GetRegisteredPythonVersions.
1 2 3 4 5 6 7 8 9 10 11 12 |
procedure TForm1.FormCreate(Sender: TObject); var PyVersion: TPythonVersion; begin PyVersions := GetRegisteredPythonVersions; for PyVersion in PyVersions do cbPyVersions.Items.Add(PyVersion.DisplayName); if cbPyVersions.Items.Count > 0 then begin cbPyVersions.ItemIndex := 0; CreatePythonComponents; end; end; |
In this Sample App, PythonEngine1, PythonModule1, PythonType1 were created dynamically when Registered Python Version is selected. The PythonVersion is assigned to PythonEngine1.
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 |
procedure TForm1.CreatePythonComponents; begin if cbPyVersions.ItemIndex <0 then begin ShowMessage('No Python version is selected'); Exit; end; // Destroy P4D components FreeAndNil(PythonEngine1); FreeAndNil(PythonType1); FreeAndNil(PythonModule1); { TPythonEngine } PythonEngine1 := TPythonEngine.Create(Self); PyVersions[cbPyVersions.ItemIndex].AssignTo(PythonEngine1); PythonEngine1.IO := PythonGUIInputOutput1; { TPythonModule } PythonModule1 := TPythonModule.Create(Self); PythonModule1.Name := 'PythonModule1'; PythonModule1.Engine := PythonEngine1; PythonModule1.ModuleName := 'spam'; with PythonModule1.Errors.Add do begin Name := 'PointError'; ErrorType := etClass; end; with PythonModule1.Errors.Add do begin Name := 'EBadPoint'; ErrorType := etClass; ParentClass.Name := 'PointError'; end; { TPythonType } PythonType1 := TPythonType.Create(Self); PythonType1.Name := 'PythonType1'; PythonType1.Engine := PythonEngine1; PythonType1.OnInitialization := PythonType1Initialization; PythonType1.TypeName := 'Point'; PythonType1.Prefix := 'Create'; PythonType1.Services.Basic := [bsRepr,bsStr,bsGetAttrO,bsSetAttrO]; PythonType1.TypeFlags := [tpfBaseType]; PythonType1.Module := PythonModule1; PythonEngine1.LoadDll; end; |
After creating the necessary components, Upon clicking the Execute button, PythonType1 created an instance of its type, added to PythonModule variable myPoint. Later the python script in Memo1.lines is executed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TForm1.Button1Click(Sender: TObject); var DelphiPoint: TPyPoint; p: PPyObject; begin p := PythonType1.CreateInstance; PythonEngine1.CheckError; DelphiPoint := TPyPoint( PythonToDelphi(p) ); DelphiPoint.X := 10; DelphiPoint.Y := 20; PythonModule1.SetVar( 'myPoint', p ); PythonEngine1.Py_DecRef(p); PythonEngine1.ExecStrings( memo1.Lines ); end; |
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition