Pointer

Top  Previous  Next

Pretranslated C# code > Pointers > Pointer

`Pointer` corresponds to the Delphi type:

 

Pointer

 

It is a non-generic, byte-addressed pointer struct implemented as a facade over `UntypedPointer`.

 

public struct Pointer : IPointer<byte>

 

`Pointer` may refer to managed storage or native storage. It is not restricted to an unmanaged allocation.

 

Creating pointers

 

Allocate owned native memory:

 

Pointer p = new Pointer(256);

 

Create a non-copying view over an existing byte array:

 

byte[] buffer = new byte[256];

Pointer p = new Pointer(buffer);

 

Wrap borrowed native memory:

 

Pointer p = new Pointer(

    existingAddress,

    size,

    ownsMemory: false);

 

If `size` is zero for a non-null address, the backing length is unknown and complete bounds checking is not possible.

 

Byte-oriented access

 

`Pointer` implements `IPointer<byte>`:

 

 

byte value = p.Deref();

p.Assign(123);

 

byte other = p.ReadByte(4);

p.WriteByte(4, other);

 

 

Typed access

 

`Read<T>(index)` and `Write<T>(index, value)` interpret `index` as an element index of type `T`:

 

TRecord record = p.Read<TRecord>(0);

p.Write<TRecord>(0, record);

 

The byte address is calculated as:

 

current byte position + index * DelphiTypeLayout.SizeOf<T>()

 

 

For an explicit byte offset, convert to `UntypedPointer` first:

 

TRecord record = p.ToUntypedPointer(byteOffset).Read<TRecord>();

 

Pointer arithmetic

 

Arithmetic is byte-based:

 

Pointer q = p + 4;

++q;

q--;

 

 

`p + 4` creates another pointer value that shares the same backing and points four bytes after `p`.

 

Because pointers are structs, pointer assignment and arithmetic do not share a mutable cursor:

 

Pointer q = p;

q++;

 

This does not move `p`.

 

Typed views

 

Create a typed view without copying:

 

Pointer<TRecord> record = p.As<TRecord>();

 

When a native API returns an address inside this pointer's backing block, `CreateView<T>` can create an owner-relative typed view:

 

Pointer<TRecord> record =

    p.CreateView<TRecord>(returnedAddress, returnedSize);

 

 

This is preferable to independently wrapping the returned address because it preserves the shared backing and lifetime relationship.

 

Conversion to and from `IntPtr`

 

IntPtr address = p;

Pointer borrowed = address;

 

The `IntPtr` value represents the current address, including the current byte offset.

 

The implicit conversion from `IntPtr` creates a borrowed pointer with unknown length. Use an explicit constructor when the accessible size is known:

 

Pointer borrowed = new Pointer(address, size, false);

 

Disposal and freeing

 

`Dispose()` clears only the current pointer value. It does not free shared memory.

 

Release an owned native allocation with:

 

DelphiMemory.FreeMem(ref p);

 

 



This page belongs to the Delphi2C# Documentation

Delphi2C# home  Content