[Implemented] Unsafe to be able to use all API's and frameworks

Pointers in VB (Unsafe).

There is a lot said about it on a lot of places and Microsoft’s answer has always been: NO.
But it is needed for a lot of API’s - so needed to get everything working in Mercury.

In VB we can not work with * or ^ - that’s not VB at all.

So I propose the following syntax:

Edited:
Ptr(Of type) like Ptr(Of Integer), Ptr(Of Object)

For functionPointers: SubPtr and FunctionPtr

Assignment:

Dim o As New Object
Dim p As Ptr(Of Object) = AddressOf o 'Use the AddresOf to get the memory location of object o

Get the memory Address (convert to IntPtr):

Dim i As IntPtr = DirectCast(p, IntPtr)

Or convert an IntPtr to a typed pointer:

Dim tp As ptr(Of Object)= DirectCast(i, Ptr(Of Object))

Dereferencing:

Dim o2 as Object = DirectCast(p, Object)

Calling a method using a functionpointer:

Call fp(param1, param2) 'no return value
Dim x = fp(param1, param2) 'with return value

Syntax for unsafe methods:

Public Unsafe Sub MyUnsafeSub()
End Sub

Same unsafe keyword for classes, structs, properties and fields

To read a pointer (the memory address) we can reintroduce the old VB keyword for reading a memory addres; PEEK - and to write it: POKE

Why Ptr(Of X) instead of the more readable Pointer(Of X)?

Because the “original” pointer in VB Classic was the VarPtr (which we could use for the Void Pointer).
To keep this up, we could also use VarPtr(Of T).

Documentation:

It’s VarPtr, StrPtr and ObjPtr in VB Classic.

Thanks, logged as bugs://84321: Mercury: Pointer support

Ok, Ptr and AddressOf it is. The only thing I’m not sold on yet is using DirectCast for dereferencing. that seems wrong. Can we come up with a better syntax/keyword?

Good point - VB never supported dereferencing before. I chose DirectCast because this is the way you change a type into another type (that it already is), so by example cast an object to an interface it implements or to it’s ancestor type.

It seemed logical to me to use this.

But I just looked up how Xojo does it, and they use a method or readonly property on the pointer with the name of the original type.
I would make that universal with a Dereference readonly property:

Public Unsafe Sub Dangerous
    Dim MyString = "ABC"
    Dim p AS Ptr(Of String) = AddressOf MyString
    For i As Integer = 0 to MyString.Length -1
        Poke(p, Peek(p + i) + 1)
    Next
    Dim DereferencedString = p.Dereference
    //both MyString as DereferencedString are now "BCD"
    //and MyString Is DereferencedString = true
End Sub
1 Like

Updated the bug description as such:

AddressOf is not a new keyword - it is already used for delegates

1 Like

Peek and Poke not in it yet?

do we re4ally need that? whats what deference is for, no?

Dim x as Ptr(Of byte) = ...
x.Dereference = 5
y = x.Dereference

isn the equivalent of

poke x, 5
y = peek x

See the string routine.
And dereference should be R/O

But why?

Why should it be read write? You are now making a reference using the dereference property.

And the instance of

p As ptr(Of Byte()) = addressof {1,2,3}

How do I change or read the second value?

because you can both set and get the value a pointer points to?

var x: ^Byte;
writeLn(x^);
x^ = 5;
writeLn(x^);

Stop using a one byte length example - show me a multi byte example.

A pointer always points to a single element of its type

var x: ^String;
writeLn(x^);
x^ = "Hello";
writeLn(x^);

or bytes:

var x: ^Byte;
writeLn(x^);
x^ = 5;
inc(x);
x^ = 6;
inc(x);
x^ = 7;

or

var x: ^Byte;
writeLn(x^);
x^ = 5;
(x+1)^ = 6;
(x+2)^ = 7;

Or do you mean this:

Dim A As String = "ABC"
Dim p As Ptr(Of Char) = String.Chars(0)
p += 1
p.Dereference = "C"

Ignoring that Chars is an enum and won’t give you an in-memory array you can use to modify the string — yes

more precisely:

Dim A As String = "ABC"
Din AChars As Char() = String.Chars.ToArray()
Dim p As Ptr(Of Char) = AddressOf AChars(0)
p += 1
p.Dereference = "C"

array now is {'A', 'C', 'C'}.