Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#1

selbstlöschenden Pointer erstellen

  Alt 28. Mär 2010, 20:35
Im Prinzip geht es darum, daß man hier "r" manuell freigeben muß.
Delphi-Quellcode:
Type TX = Record
    a: Integer;
    r: ^TFormatSettings;
  End;
Also hab ich mal versucht, dieses zu automatisieren.
Aber so ganz Glücklich bin ich mit meiner ersten Lösung noch nicht.

OK, eine Anfrage bei Emba, ob die nicht mal einen Constructor und vorallem einen Destructor für Records implementieren können ist gestellt, aber eine Antwort gab es bißher noch nicht und ob es jemals sowas geben wird ......

Gut, also kann man nur noch die Compilermagic und andere sich selbst freigebende Dinge verwenden.

Da wären also Strings, dynamische Arrays und Interfaces.
Ich hab mich natürlich für das Interface entschieden.


Hier also nochmal der selbe Record von oben, nur eben mit einem Interface dazwischen:
Delphi-Quellcode:
Program Project4;

{$APPTYPE CONSOLE}

Uses SysUtils, Unit4;

Type TX = Record
    a: Integer;
    r: TSelfDestrucionPointer<TFormatSettings>;
  End;

Var X: TX;
  F: TFormatSettings;

Begin
  Try
    X.r.Alloc;
    X.r.PData^.NegCurrFormat := 2;
    If X.r.Data.NegCurrFormat = 1 Then ;
    F := X.r;
    If F.NegCurrFormat = 1 Then ;
  Except
    On E: Exception do
      WriteLn(E.ClassName, ': ', E.Message);
  End;
End.
Und die nötigen Klassen:
Delphi-Quellcode:
Unit Unit4;

Interface
  Type IInternalSelfDestrucionPointer = Interface
      Function Data: Pointer;
    End;
    TInternalSelfDestrucionPointer = Class(TInterfacedObject, IInternalSelfDestrucionPointer)
    Protected
      _TypeInfo: Pointer;
      _Data: Pointer;
    Public
      Constructor Create(Size: Integer; TypeInfo: Pointer);
      Destructor Destroy; Override;
      Function Data: Pointer;
    End;

    TSelfDestrucionPointer<Typ> = Record
    Private
      _Data: IInternalSelfDestrucionPointer;
      Type PTyp = ^Typ;
      Procedure SetData(Const Data: Typ);
      Function GetData: Typ;
      Function GetPData: PTyp;
    Public
      Class Operator Implicit(Const X: TSelfDestrucionPointer<Typ>): Typ;
      Class Operator Implicit(Const X: Typ): TSelfDestrucionPointer<Typ>;
      Property Data: Typ Read GetData Write SetData;
      Property PData: PTyp Read GetPData;
      Procedure Alloc;
      Procedure Free;
    End;

Implementation
  Constructor TInternalSelfDestrucionPointer.Create(Size: Integer; TypeInfo: Pointer);
    Begin
      _Data := GetMemory(Size);
      _TypeInfo := TypeInfo;
      FillChar(_Data^, Size, 0);
    End;

  Destructor TInternalSelfDestrucionPointer.Destroy;
    Begin
      FinalizeArray(@_Data, _TypeInfo, 1);
      FreeMemory(_Data);
    End;

  Function TInternalSelfDestrucionPointer.Data: Pointer;
    Begin
      Result := _Data;
    End;

  Procedure TSelfDestrucionPointer<Typ>.SetData(Const Data: Typ);
    Begin
      If not Assigned(_Data) Then
        _Data := TInternalSelfDestrucionPointer.Create(SizeOf(Typ), TypeInfo(Typ));
      PTyp(_Data.Data)^ := Data;
    End;

  Function TSelfDestrucionPointer<Typ>.GetData: Typ;
    Begin
      If not Assigned(_Data) Then Begin
        Finalize(Result);
        FillChar(Result, SizeOf(Typ), 0);
      End Else Result := PTyp(_Data.Data)^;
    End;

  Function TSelfDestrucionPointer<Typ>.GetPData: PTyp;
    Begin
      If not Assigned(_Data) Then Result := nil
      Else Result := PTyp(_Data.Data);
    End;

  Class Operator TSelfDestrucionPointer<Typ>.Implicit(Const X: TSelfDestrucionPointer<Typ>): Typ;
    Begin
      If not Assigned(X._Data) Then Begin
        Finalize(Result);
        FillChar(Result, SizeOf(Typ), 0);
      End Else Result := PTyp(X._Data.Data)^;
    End;

  Class Operator TSelfDestrucionPointer<Typ>.Implicit(Const X: Typ): TSelfDestrucionPointer<Typ>;
    Begin
      Result._Data := TInternalSelfDestrucionPointer.Create(SizeOf(Typ), TypeInfo(Typ));
      PTyp(Result._Data.Data)^ := X;
    End;

  Procedure TSelfDestrucionPointer<Typ>.Alloc;
    Begin
      _Data := TInternalSelfDestrucionPointer.Create(SizeOf(Typ), TypeInfo(Typ));
    End;

  Procedure TSelfDestrucionPointer<Typ>.Free;
    Begin
      _Data := nil;
    End;

End.
Nunja, grundsätzlich läuft dieses erstmal, auch wenn ich noch einiges ändern werde:
- der Typ/Record muß noch direkt in die Objektinstanz rein
(ein Speicherblock reicht ja ... jetzt sind es noch 2 ... einmal der Record und dann noch das Objekt)

Nur leider ist es nicht möglich dem Interface-Zeiger und dem Pointer auf den Record den den selben Wert zu geben

Gut, also die selben "Zeiger" sind also nicht möglich, aber wenn ich es wenigstens schaffe die Zugriffe, bzw. die Befehle für den Zugriff, halbwegs identisch aussehn zu lassen (vom Quellcode her), dann wäre es für meine Zwecke schonmal nutzbar.

Folgendes ist ja leider nicht nutzbar, auch wenn ich, Aufgrund von Implicit wenigstens einen Lesezugriff erwartet hätte.
Zitat:
X.r.NegCurrFormat
X.r^.NegCurrFormat


Nun die Fragen:

- Ist sowas überhaupt ausbaufähig aka könnten Andere sowas mal gebrauchen?
- Hat jemand Ideen, Vorschläge, Kritik?
- ...
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat