forked from Embarcadero/python4delphi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuMain.pas
More file actions
160 lines (134 loc) · 4.37 KB
/
Copy pathuMain.pas
File metadata and controls
160 lines (134 loc) · 4.37 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
unit uMain;
interface
uses PythonEngine;
function PyInit_DelphiVCL: PPyObject; cdecl;
implementation
uses System.IOUtils, System.SysUtils, System.JSON, WrapDelphi, WrapDelphiVCL;
var
gEngine : TPythonEngine;
gModule : TPythonModule;
gDelphiWrapper : TPyDelphiWrapper;
function GetModuleDir(): string;
begin
Result := ExtractFilePath(GetModuleName(HInstance));
end;
function GetModuleDefsDir(): string;
begin
Result := TDirectory.GetParent(ExcludeTrailingPathDelimiter(GetModuleDir()));
end;
function GetModuleDefsLogFilePath(): string;
const
MODULE_DEFS_LOG = 'moduledefs.log';
begin
Result := TPath.Combine(GetModuleDefsDir(), MODULE_DEFS_LOG, false);
end;
function GetModuleDefsJSONFilePath(): string;
const
MODULE_DEFS_JSON = 'moduledefs.json';
begin
Result := TPath.Combine(GetModuleDefsDir(), MODULE_DEFS_JSON, false);
end;
procedure Dump(const AText: string);
begin
try
TFile.AppendAllText(GetModuleDefsLogFilePath(),
DateTimeToStr(Now())
+ ': '
+ AText
+ sLineBreak);
except
on E: Exception do
TFile.AppendAllText(TPath.Combine(
GetCurrentDir(), 'dump.txt', false), E.Message
+ sLineBreak
+ 'while dumping: '
+ AText
+ sLineBreak);
end;
end;
function TryLoadVerFromModuleDefs(): boolean;
begin
//Load Python using the moduledefs.json file - it cracks the single version limitation
var LFilePath := GetModuleDefsJSONFilePath();
if TFile.Exists(LFilePath) then begin
var LJson := TJSONObject.ParseJSONValue(TFile.ReadAllText(LFilePath));
if not Assigned(LJson) then
Exit(false);
var LPythonHome := String.Empty;
if LJson.TryGetValue<string>('python_home', LPythonHome) then begin
gEngine.PythonHome := LPythonHome;
end;
var LPythonBin := String.Empty;
if LJson.TryGetValue<string>('python_bin', LPythonBin) then begin
gEngine.ProgramName := LPythonBin;
end;
var LPythonLib := String.Empty;
if LJson.TryGetValue<string>('python_lib', LPythonLib) then begin
gEngine.DllPath := LPythonLib;
end;
var LPythonSharedLib := String.Empty;
if LJson.TryGetValue<string>('python_shared_lib', LPythonSharedLib) then begin
gEngine.DllName := LPythonSharedLib;
end;
var LPythonVer: string;
if LJson.TryGetValue<string>('python_ver', LPythonVer) then begin
for var I := Low(PYTHON_KNOWN_VERSIONS) to High(PYTHON_KNOWN_VERSIONS) do begin
if (PYTHON_KNOWN_VERSIONS[I].RegVersion = LPythonVer) then begin
gEngine.RegVersion := PYTHON_KNOWN_VERSIONS[I].RegVersion;
if LPythonSharedLib.IsEmpty() then
gEngine.DllName := PYTHON_KNOWN_VERSIONS[I].DllName;
Dump(Format('Module has been set to Python %s using the module defs file', [gEngine.RegVersion]));
Exit(true);
end;
end;
end;
end;
Result := false;
end;
function TryLoadVerFromIncFile(): boolean;
begin
// Adapt to the desired python version - Will only work with this version
var PythonVersionIndex := {$I PythonVersionIndex.inc}; // 7 = 3.9
gEngine.RegVersion := PYTHON_KNOWN_VERSIONS[PythonVersionIndex].RegVersion;
gEngine.DllName := PYTHON_KNOWN_VERSIONS[PythonVersionIndex].DllName;
Dump(Format('Module has been set to Python %s using the version index file', [gEngine.RegVersion]));
Exit(true);
end;
// This must match the pattern "PyInit_[ProjectName]"
// So if the project is named DelphiVCL then
// the function must be PyInit_DelphiVCL
function PyInit_DelphiVCL: PPyObject;
begin
try
gEngine := TPythonEngine.Create(nil);
gEngine.AutoFinalize := False;
gEngine.UseLastKnownVersion := False;
if not TryLoadVerFromModuleDefs() then
if not TryLoadVerFromIncFile() then
Exit(gEngine.ReturnNone);
gModule := TPythonModule.Create(nil);
gModule.Engine := gEngine;
// This must match the ProjectName and the function name pattern
gModule.ModuleName := 'DelphiFMX';
gDelphiWrapper := TPyDelphiWrapper.Create(nil);
gDelphiWrapper.Engine := gEngine;
gDelphiWrapper.Module := gModule;
gEngine.LoadDll;
Result := gModule.Module;
except
on E: Exception do begin
WriteLn('An error occurred: ' + E.Message);
Dump(E.Message);
Result := gEngine.ReturnNone;
end;
end;
end;
initialization
gEngine := nil;
gModule := nil;
gDelphiWrapper := nil;
finalization
gEngine.Free;
gModule.Free;
gDelphiWrapper.Free;
end.