|
DelphiCell |
Top Previous Next |
|
Pretranslated C# code > Pointers > DelphiCell
Overview
`DelphiCell<T>` represents an addressable variable containing a single value of type `T`.
It is used by Delphi2C# when translated Delphi code takes the address of a local variable or passes a local variable to an untyped `var` parameter.
In Delphi, the address of a local variable can be obtained with the `@` operator:
var Value: Integer; P: PInteger; begin Value := 10; P := @Value; P^ := 20; end;
After the pointer assignment, both `Value` and `P^` refer to the same storage location.
A normal C# local variable cannot be represented directly by the managed pointer runtime in this way. `DelphiCell<T>` therefore stores the value in a small shared storage object that can be accessed both as a value and through a pointer.
Declaration
public sealed class DelphiCell<T> { public DelphiCell(); public DelphiCell(T value);
public T Value { get; set; }
public Pointer<T> AsPointer(); public UntypedPointer AsUntypedPointer(); }
Creating a cell
A cell can be created with the default value of `T`:
DelphiCell<int> value = new DelphiCell<int>();
It can also be initialized with a value:
DelphiCell<int> value = new DelphiCell<int>(10);
The contained value is accessed through the `Value` property:
value.Value = 20;
int currentValue = value.Value;
Creating a typed pointer
`AsPointer()` returns a `Pointer<T>` that refers to the value stored in the cell:
DelphiCell<int> value = new DelphiCell<int>(10); Pointer<int> pointer = value.AsPointer();
pointer.Assign(20);
After the assignment, both expressions return `20`:
value.Value pointer.Deref()
The pointer does not contain a separate copy of the value. The cell and the pointer share the same backing storage.
Creating an untyped pointer
`AsUntypedPointer()` returns an `UntypedPointer` that refers to the same storage location:
DelphiCell<int> value = new DelphiCell<int>(100); UntypedPointer pointer = value.AsUntypedPointer();
pointer.As<int>().Assign(200);
After the assignment:
value.Value == 200
This is especially useful for translating untyped Delphi parameters.
For example, the Delphi declaration
procedure WriteValue(var AValue);
can be translated as:
public static void WriteValue(UntypedPointer aValue) { Pointer<int> pointer = aValue.As<int>(); pointer.Assign(31415); }
The procedure can then be called with a cell:
DelphiCell<int> value = new DelphiCell<int>(0);
WriteValue(value.AsUntypedPointer());
After the call:
value.Value == 31415
Translation of local variables
A Delphi local variable whose address is never taken can normally remain a standard C# local variable.
Delphi:
var Value: Integer; begin Value := 10; end;
C#:
int value = 10;
If the Delphi code takes the address of the variable, Delphi2C# must use `DelphiCell<T>`.
Delphi:
var Value: Integer; P: PInteger; begin Value := 10; P := @Value; P^ := 20; end;
C#:
DelphiCell<int> value = new DelphiCell<int>(10); Pointer<int> pointer = value.AsPointer();
pointer.Assign(20);
The original variable must then be accessed through its `Value` property:
bool result = value.Value == 20 && pointer.Deref() == 20;
Why an array is used internally
`DelphiCell<T>` stores its value in an array containing exactly one element.
This provides a shared reference-based storage location that can be used by the pointer runtime. Multiple pointer views can refer to the same array element, and changes made through one view are visible through all other views.
Conceptually, the storage is equivalent to:
T[] storage = new T[1];
The `Value` property accesses `storage[0]`, while `AsPointer()` and `AsUntypedPointer()` create pointer views of the same element.
The array is an implementation detail and is not exposed publicly.
Difference from Pointer<T>(value)
Creating a pointer directly from a value creates a new storage location containing a copy:
int value = 10; Pointer<int> pointer = new Pointer<int>(value);
pointer.Assign(20);
The original variable remains unchanged:
value == 10
Using `DelphiCell<T>` creates shared storage instead:
DelphiCell<int> value = new DelphiCell<int>(10); Pointer<int> pointer = value.AsPointer();
pointer.Assign(20);
Now the cell contains the modified value:
value.Value == 20
For this reason, `DelphiCell<T>` must be used when translated code requires pointer writes to modify the original local variable.
Pointer copies
Pointers created from the same cell continue to refer to the same value:
DelphiCell<int> value = new DelphiCell<int>(10);
Pointer<int> pointer1 = value.AsPointer(); Pointer<int> pointer2 = pointer1;
pointer2.Assign(30);
All views now return the same value:
value.Value == 30 pointer1.Deref() == 30 pointer2.Deref() == 30
Lifetime
The backing storage remains available while the cell or one of its pointer views is referenced.
However, translated code should preserve the logical lifetime rules of the original Delphi local variable. A pointer to a local variable should not normally be stored and used after the translated method has finished.
Recommended generator mapping
@LocalVariable -> DelphiCell<T> localVariable Pointer<T> pointer = localVariable.AsPointer()
For an untyped `var` parameter:
UntypedProcedure(LocalVariable) -> UntypedProcedure(localVariable.AsUntypedPointer())
Normal reads and writes of the translated variable must use the `Value` property:
LocalVariable := Value -> localVariable.Value = value
Value := LocalVariable -> value = localVariable.Value
Example
Delphi:
function TestLocalVariableAddress: Boolean; var LocalValue: Integer; P: PInteger; begin LocalValue := 111;
P := @LocalValue; P^ := 222;
Result := (LocalValue = 222) and (P^ = 222); end;
C#:
public static bool TestLocalVariableAddress() { bool result = false;
DelphiCell<int> localValue = new DelphiCell<int>(111);
Pointer<int> pointer = localValue.AsPointer();
pointer.Assign(222);
result = localValue.Value == 222 && pointer.Deref() == 222;
return result; }
Summary
`DelphiCell<T>` is used to represent a single addressable value in translated C# code.
It provides:
The class is normally required only when Delphi code takes the address of a local variable or passes it through an untyped writable parameter.
|
|
This page belongs to the Delphi2C# Documentation |
Delphi2C# home Content |