@@ -1902,7 +1902,8 @@ TPythonEngine = class(TPythonInterface)
1902
1902
procedure AddClient ( client : TEngineClient );
1903
1903
procedure RemoveClient ( client : TEngineClient );
1904
1904
function FindClient ( const aName : string ) : TEngineClient;
1905
- function FindPythonType ( const TypeName : AnsiString ) : TPythonType;
1905
+ function FindPythonType (const TypeName : AnsiString): TPythonType; overload;
1906
+ function FindPythonType (PyType: PPyTypeObject): TPythonType; overload;
1906
1907
function TypeByName ( const aTypeName : AnsiString ) : PPyTypeObject;
1907
1908
function ModuleByName ( const aModuleName : AnsiString ) : PPyObject;
1908
1909
function MethodsByName ( const aMethodsContainer: string ) : PPyMethodDef;
@@ -2362,6 +2363,20 @@ TPythonModule = class(TMethodsContainer)
2362
2363
- When turning a Delphi instance into a Python object pointer, GetSelf will offset
2363
2364
Self from B to A.
2364
2365
- Properties ob_refcnt and ob_type will call GetSelf to access their data.
2366
+
2367
+ Further Notes:
2368
+ - PyObject instances are not created directly, but via their python type
2369
+ See TPythonType.CreateInstance and TPythonType.NewSubtypeInst (tp_new
2370
+ slot). In the second case TPy_Object.NewInstance is not called and
2371
+ the size of the memory is determined by the tp_basicsize slot.
2372
+ - Their memory can be allocated either by pascal or python. PythonAlloc
2373
+ keeps track of how the PyObject memory was allocated.
2374
+ - PyObject instances are not destroyed directly, but by PyObjectDestructor
2375
+ when their reference count goes down to zero (tp_dealloc slot)
2376
+ - The value of PythonAlloc determines how the memory is freed
2377
+ using either PyObject_Free (tp_free slot) or in the overwritten
2378
+ FreeInstance.
2379
+ - This class is heart of the P4D library. Pure magic!!
2365
2380
}
2366
2381
// The base class of all new Python types
2367
2382
TPyObject = class
@@ -2767,7 +2782,6 @@ function PythonOK : Boolean;
2767
2782
function PythonToDelphi ( obj : PPyObject ) : TPyObject;
2768
2783
function IsDelphiObject ( obj : PPyObject ) : Boolean;
2769
2784
procedure PyObjectDestructor ( pSelf : PPyObject); cdecl;
2770
- procedure FreeSubtypeInst (ob:PPyObject); cdecl;
2771
2785
procedure Register ;
2772
2786
function PyType_HasFeature (AType : PPyTypeObject; AFlag : Integer) : Boolean;
2773
2787
function SysVersionFromDLLName (const DLLFileName : string): string;
@@ -6139,6 +6153,19 @@ function TPythonEngine.FindPythonType(const TypeName: AnsiString): TPythonType;
6139
6153
end ;
6140
6154
end ;
6141
6155
6156
+ function TPythonEngine.FindPythonType (PyType: PPyTypeObject): TPythonType;
6157
+ var
6158
+ I : Integer;
6159
+ begin
6160
+ Result := nil ;
6161
+ for I := 0 to ClientCount - 1 do
6162
+ if (Clients[I] is TPythonType) and (TPythonType(Clients[I]).TheTypePtr = PyType) then
6163
+ begin
6164
+ Result := TPythonType(Clients[I]);
6165
+ Break;
6166
+ end ;
6167
+ end ;
6168
+
6142
6169
function TPythonEngine.FindFunction (const ModuleName,FuncName: AnsiString): PPyObject;
6143
6170
var
6144
6171
module ,func: PPyObject;
@@ -8178,6 +8205,9 @@ function TPythonType.NewSubtypeInst( aType: PPyTypeObject; args, kwds : PPyObje
8178
8205
var
8179
8206
obj : TPyObject;
8180
8207
begin
8208
+ // Allocate memory in the python heap for both the pascal and the python
8209
+ // PyObject (see tp_basicsize in SetPyObjectClass)
8210
+ // nitems = 0 because PyType_GenericAlloc adds +1
8181
8211
Result := aType^.tp_alloc(aType, 0 );
8182
8212
if Assigned(Result) then
8183
8213
begin
@@ -8191,21 +8221,11 @@ function TPythonType.NewSubtypeInst( aType: PPyTypeObject; args, kwds : PPyObje
8191
8221
begin
8192
8222
Engine.Py_DECREF(Result);
8193
8223
Result := nil ;
8224
+ obj.Free;
8194
8225
end ;
8195
8226
end ;
8196
8227
end ;
8197
8228
8198
- function TPythonType_AllocSubtypeInst ( pSelf: PPyTypeObject; nitems : NativeInt) : PPyObject; cdecl;
8199
- begin
8200
- Result := GetPythonEngine.PyType_GenericAlloc(pSelf, nitems);
8201
- end ;
8202
-
8203
- procedure FreeSubtypeInst (ob:PPyObject);
8204
- begin
8205
- GetPythonEngine.PyObject_Free(ob);
8206
- end ;
8207
-
8208
-
8209
8229
// Number services
8210
8230
8211
8231
function TPythonType_NbAdd ( pSelf, obj : PPyObject) : PPyObject; cdecl;
@@ -8484,9 +8504,9 @@ procedure TPythonType.InitServices;
8484
8504
if tpfBaseType in TypeFlags then
8485
8505
begin
8486
8506
tp_init := TPythonType_InitSubtype;
8487
- tp_alloc := TPythonType_AllocSubtypeInst ;
8507
+ tp_alloc := FEngine.PyType_GenericAlloc ;
8488
8508
tp_new := GetCallBack( Self, @TPythonType.NewSubtypeInst, 3 , DEFAULT_CALLBACK_TYPE);
8489
- tp_free := FreeSubtypeInst ;
8509
+ tp_free := FEngine.PyObject_Free ;
8490
8510
tp_methods := MethodsData;
8491
8511
tp_members := MembersData;
8492
8512
tp_getset := GetSetData;
0 commit comments