Skip to content

Commit 033c4ad

Browse files
committed
Free always frees DelphiObject Ownership affects what happens when the Python object is destroyed when its reference Count goes down to zero.
1 parent cd59093 commit 033c4ad

File tree

3 files changed

+24
-12
lines changed

3 files changed

+24
-12
lines changed

Source/WrapDelphi.pas

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,6 @@ TPyDelphiObject = class (TPyInterfacedObject, IFreeNotificationSubscriber)
521521
function GetContainerAccess: TContainerAccess;
522522
procedure SetDelphiObject(const Value: TObject);
523523
protected
524-
fCanFreeOwnedObject : Boolean;
525-
526524
function CheckBound : Boolean;
527525
function HasContainerAccessClass : Boolean;
528526
procedure SubscribeToFreeNotification; virtual;
@@ -906,7 +904,6 @@ implementation
906904
rs_ErrSqAss = 'Container %s does not support indexed write (f[i] = x)';
907905
rs_ErrSqContains = 'Container %s does not support the Contains protocol';
908906
rs_ErrCheckBound = 'Delphi wrapper %s is not bound';
909-
rs_ErrFree = 'The Delphi object cannot be freed, since it is not Owned';
910907
rs_ErrSequence = 'Wrapper %s does not support sequences';
911908
rs_ErrInvalidArgs = '"%s" called with invalid arguments.'#$A'Error: %s';
912909
rs_ErrInvalidRet = 'Call "%s" returned a value that could not be coverted to Python'#$A'Error: %s';
@@ -1778,15 +1775,13 @@ function TPyDelphiObject.Free_Wrapper(args: PPyObject): PPyObject;
17781775
begin
17791776
if PyArg_ParseTuple( args, ':Free' ) <> 0 then
17801777
begin
1781-
if Owned or fCanFreeOwnedObject then begin
1782-
DelphiObject := nil; // this will free the object automatically
1783-
Owned := False;
1784-
Result := ReturnNone;
1785-
end else begin
1786-
PyErr_SetObject (PyExc_AttributeError^,
1787-
PyUnicodeFromString(rs_ErrFree));
1788-
Result := nil;
1778+
if Assigned(fDelphiObject)then
1779+
begin
1780+
UnSubscribeToFreeNotification;
1781+
FreeAndNil(fDelphiObject);
17891782
end;
1783+
Owned := False;
1784+
Result := ReturnNone;
17901785
end
17911786
else
17921787
Result := nil;

Source/WrapDelphiClasses.pas

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,6 @@ constructor TPyDelphiComponent.CreateWith(APythonType: TPythonType;
10241024
begin
10251025
DelphiObject := CreateComponent(TComponent(_owner));
10261026
Owned := not Assigned(_owner);
1027-
fCanFreeOwnedObject := True;
10281027
end;
10291028
end;
10301029
end;

Tests/WrapDelphiTest.pas

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ TTestRttiAccess = class
4747
ObjectField: TObject;
4848
RecordField: TTestRecord;
4949
InterfaceField: ITestInterface;
50+
function GetData: TObject;
5051
procedure BuyFruits(AFruits: TFruits);
5152
procedure SellFruits(const AFruits: TFruitDynArray);
5253
procedure SellFruitsInt(const AFruits:TIntegerDynArray);
@@ -116,6 +117,8 @@ TTestWrapDelphi = class(TObject)
116117
procedure TestGetStaticArray;
117118
[Test]
118119
procedure TestMethodWithVarAndOverload;
120+
[Test]
121+
procedure FreeReturnedObject;
119122
end;
120123

121124
implementation
@@ -139,6 +142,16 @@ procedure TTestRttiAccess.BuyFruits(AFruits: TFruits);
139142

140143
{ TTestVarPyth }
141144

145+
procedure TTestWrapDelphi.FreeReturnedObject;
146+
begin
147+
PythonEngine.ExecString(
148+
'from delphi import rtti_var' + sLineBreak +
149+
'obj = rtti_var.GetData()' + sLineBreak +
150+
'obj.Free()'
151+
);
152+
Assert.Pass;
153+
end;
154+
142155
procedure TTestWrapDelphi.SetupFixture;
143156
var
144157
Py : PPyObject;
@@ -417,6 +430,11 @@ function TTestRttiAccess.SetStringField(var Value: Integer): string;
417430
Result := StringField;
418431
end;
419432

433+
function TTestRttiAccess.GetData: TObject;
434+
begin
435+
Result := TStringList.Create;
436+
end;
437+
420438
function TTestRttiAccess.GetDynArray: TInt64DynArray;
421439
var
422440
I: Integer;

0 commit comments

Comments
 (0)