Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aaeb97e

Browse files
committed
Including support for host symbols
1 parent 6fe44aa commit aaeb97e

File tree

1 file changed

+80
-3
lines changed

1 file changed

+80
-3
lines changed

Source/PythonEngine.pas

+80-3
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,8 @@ TDynamicDll = class(TComponent)
11811181
procedure DoOpenDll(const aDllName : string); virtual;
11821182
function GetDllPath : string;
11831183

1184+
function HasHostSymbols(): boolean;
1185+
procedure LoadFromHostSymbols();
11841186
public
11851187
// Constructors & Destructors
11861188
constructor Create(AOwner: TComponent); override;
@@ -2727,6 +2729,8 @@ procedure Register;
27272729
function PyType_HasFeature(AType : PPyTypeObject; AFlag : Integer) : Boolean;
27282730
function SysVersionFromDLLName(const DLLFileName : string): string;
27292731
procedure PythonVersionFromDLLName(LibName: string; out MajorVersion, MinorVersion: integer);
2732+
function SpliVersionFromRegVersion(const ARegVersion: string;
2733+
out AMajorVersion, AMinorVersion: integer): boolean;
27302734

27312735
{ Helper functions}
27322736
(*
@@ -3083,15 +3087,62 @@ function TDynamicDll.IsHandleValid : Boolean;
30833087
{$ENDIF}
30843088
end;
30853089

3090+
procedure TDynamicDll.LoadFromHostSymbols;
3091+
var
3092+
LPy_GetVersion: function: PAnsiChar; cdecl;
3093+
LPy_GetProgramFullPath: function: PAnsiChar; cdecl;
3094+
LVersion: string;
3095+
LInfo: TPythonVersionProp;
3096+
LFound: boolean;
3097+
begin
3098+
BeforeLoad();
3099+
//According to the doc:
3100+
//Return the full program name of the Python executable.
3101+
//The value is available to Python code as sys.executable.
3102+
LPy_GetProgramFullPath := Import('Py_GetProgramFullPath');
3103+
DllName := ExtractFileName(String(LPy_GetProgramFullPath()));
3104+
3105+
//According to the doc:
3106+
//The first word (up to the first space character) is the current Python version
3107+
LPy_GetVersion := Import('Py_GetVersion');
3108+
LVersion := String(LPy_GetVersion());
3109+
LVersion := Copy(LVersion, 1, Pos(' ', LVersion));
3110+
//the first three characters are the major and minor version separated by a period.
3111+
if (Length(LVersion) > 3) and (LVersion[4] <> '.') then
3112+
LVersion := Copy(LVersion, 1, 4) //e.g. 3.10
3113+
else
3114+
LVersion := Copy(LVersion, 1, 3); //e.g. 3.9
3115+
3116+
LFound := false;
3117+
for LInfo in PYTHON_KNOWN_VERSIONS do
3118+
if (LInfo.RegVersion = LVersion) then begin
3119+
RegVersion := LInfo.RegVersion;
3120+
APIVersion := LInfo.APIVersion;
3121+
LFound := true;
3122+
Break;
3123+
end;
3124+
3125+
if not LFound then
3126+
raise EDLLLoadError.Create('Undetermined Python version from host symbols.');
3127+
3128+
AfterLoad();
3129+
end;
3130+
30863131
procedure TDynamicDll.LoadDll;
30873132
begin
30883133
OpenDll( DllName );
30893134
end;
30903135

30913136
procedure TDynamicDll.LoadDllInExtensionModule;
30923137
begin
3138+
//We want to look in for host symbols at first
3139+
FDLLHandle := 0;
3140+
30933141
FInExtensionModule := True;
3094-
LoadDLL;
3142+
if HasHostSymbols() then
3143+
LoadFromHostSymbols()
3144+
else
3145+
LoadDLL;
30953146
end;
30963147

30973148
procedure TDynamicDll.UnloadDll;
@@ -3126,6 +3177,17 @@ function TDynamicDll.GetQuitMessage : string;
31263177
Result := Format( 'Dll %s could not be loaded. We must quit.', [DllName]);
31273178
end;
31283179

3180+
function TDynamicDll.HasHostSymbols: boolean;
3181+
var
3182+
LPy_IsInitialized: function: integer; cdecl;
3183+
begin
3184+
if not ModuleIsLib then
3185+
Exit(false);
3186+
3187+
LPy_IsInitialized := Import('Py_IsInitialized', false);
3188+
Result := Assigned(LPy_IsInitialized) and (LPy_IsInitialized() <> 0);
3189+
end;
3190+
31293191
procedure TDynamicDll.Quit;
31303192
begin
31313193
if not( csDesigning in ComponentState ) then begin
@@ -3182,7 +3244,10 @@ constructor TPythonInterface.Create(AOwner: TComponent);
31823244
procedure TPythonInterface.AfterLoad;
31833245
begin
31843246
inherited;
3185-
PythonVersionFromDLLName(DLLName, FMajorVersion, FMinorVersion);
3247+
if not FInExtensionModule then
3248+
PythonVersionFromDLLName(DLLName, FMajorVersion, FMinorVersion)
3249+
else if not SpliVersionFromRegVersion(RegVersion, FMajorVersion, FMinorVersion) then
3250+
raise EDLLLoadError.Create('Undetermined Python version.');
31863251

31873252
FBuiltInModuleName := 'builtins';
31883253

@@ -3578,7 +3643,7 @@ procedure TPythonInterface.MapDll;
35783643
Py_GetPrefix := Import('Py_GetPrefix');
35793644
Py_GetProgramName := Import('Py_GetProgramName');
35803645

3581-
if (FMajorVersion = 3) and (MinorVersion < 10) then
3646+
if (FMajorVersion = 3) and (FMinorVersion < 10) then
35823647
begin
35833648
PyParser_SimpleParseStringFlags := Import('PyParser_SimpleParseStringFlags');
35843649
PyNode_Free := Import('PyNode_Free');
@@ -9188,6 +9253,18 @@ procedure PythonVersionFromDLLName(LibName: string; out MajorVersion, MinorVersi
91889253
MinorVersion:= StrToIntDef(LibName, DefaultMinor);
91899254
end;
91909255

9256+
function SpliVersionFromRegVersion(const ARegVersion: string;
9257+
out AMajorVersion, AMinorVersion: integer): boolean;
9258+
var
9259+
LSepPos: integer;
9260+
begin
9261+
//RegVersion supported format: [x.x or x.xx or x[..].x[..]]
9262+
LSepPos := Pos('.', ARegVersion);
9263+
AMajorVersion := StrToIntDef(Copy(ARegVersion, 1, LSepPos - 1), 0);
9264+
AMinorVersion := StrToIntDef(Copy(ARegVersion, LSepPos + 1, Length(ARegVersion) - LSepPos), 0);
9265+
9266+
Result := (AMajorVersion > 0) and (AMinorVersion > 0);
9267+
end;
91919268

91929269
end.
91939270

0 commit comments

Comments
 (0)