Skip to content

Commit f9be506

Browse files
committed
A new function SafePyEngine was added. It facilitates running python code in Delphi threads.
1 parent dfd53b5 commit f9be506

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

Source/PythonEngine.pas

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,21 +2915,43 @@ function PythonVersionFromRegVersion(const ARegVersion: string;
29152915
out AMajorVersion, AMinorVersion: integer): boolean;
29162916
function PyStatus_Exception(const APyStatus: PyStatus): Boolean;
29172917

2918+
//#######################################################
2919+
//## ##
2920+
//## Support routines for running python ##
2921+
//## code in threads ##
2922+
//## ##
2923+
//#######################################################
2924+
2925+
type
2926+
IPyEngineAndGIL = interface
2927+
function GetPyEngine: TPythonEngine;
2928+
function GetThreadState: PPyThreadState;
2929+
property PythonEngine: TPythonEngine read GetPyEngine;
2930+
property ThreadState: PPyThreadState read GetThreadState;
2931+
end;
2932+
2933+
// Access the PythonEngine with thread safety
2934+
function SafePyEngine: IPyEngineAndGIL;
2935+
2936+
29182937
{ Helper functions}
2938+
29192939
(*
29202940
Checks whether the PythonVersion x.x is Registered
29212941
*)
29222942
{$IFDEF MSWINDOWS}
29232943
function IsPythonVersionRegistered(PythonVersion : string;
29242944
out InstallPath: string; out AllUserInstall: Boolean) : Boolean;
29252945
{$ENDIF}
2946+
29262947
(*
29272948
Mask FPU Excptions - Useful for importing SciPy and other Python libs
29282949
See http://bugs.python.org/issue9980 and
29292950
http://stackoverflow.com/questions/3933851/
29302951
*)
29312952
procedure MaskFPUExceptions(ExceptionsMasked : boolean;
29322953
MatchPythonPrecision : Boolean = True);
2954+
29332955
(*
29342956
Converts line breaks to LF and optionally adds a line break at the end
29352957
*)
@@ -9788,5 +9810,53 @@ function PyStatus_Exception(const APyStatus: PyStatus): Boolean;
97889810
Result := APyStatus._type <> _PyStatus_TYPE_OK;
97899811
end;
97909812

9813+
{ TPyEngineAndGIL - Internal class for SafePythonEngine }
9814+
9815+
type
9816+
TPyEngineAndGIL = class(TInterfacedObject, IPyEngineAndGIL)
9817+
fPythonEngine: TPythonEngine;
9818+
fThreadState: PPyThreadState;
9819+
fGILState: PyGILstate_STATE;
9820+
private
9821+
function GetPyEngine: TPythonEngine;
9822+
function GetThreadState: PPyThreadState;
9823+
public
9824+
constructor Create;
9825+
destructor Destroy; override;
9826+
end;
9827+
9828+
9829+
constructor TPyEngineAndGIL.Create;
9830+
begin
9831+
inherited Create;
9832+
fPythonEngine := GetPythonEngine;
9833+
fGILState := fPythonEngine.PyGILState_Ensure;
9834+
fThreadState := fPythonEngine.PyThreadState_Get;
9835+
end;
9836+
9837+
destructor TPyEngineAndGIL.Destroy;
9838+
begin
9839+
fPythonEngine.PyGILState_Release(fGILState);
9840+
inherited;
9841+
end;
9842+
9843+
function TPyEngineAndGIL.GetPyEngine: TPythonEngine;
9844+
begin
9845+
Result := fPythonEngine;
9846+
end;
9847+
9848+
function TPyEngineAndGIL.GetThreadState: PPyThreadState;
9849+
begin
9850+
Result := fThreadState;
9851+
end;
9852+
9853+
{ SafePythonEngine }
9854+
function SafePyEngine: IPyEngineAndGIL;
9855+
begin
9856+
Result := TPyEngineAndGIL.Create
9857+
end;
9858+
9859+
9860+
97919861
end.
97929862

0 commit comments

Comments
 (0)