Re: Typed properties - experimental build available
Posted: 26 Mar 2024, 06:18
Should the __value.get of the pointer class be removed, so that null pointers can be retrieved?
Let's help each other out
https://www.autohotkey.com/boards/
https://www.autohotkey.com/boards/viewtopic.php?f=37&t=119420
Code: Select all
fn() {
static RECT := () {
obj := Class(Object)
for k in ['x', 'y', 'w', 'h']
obj.Prototype.DefineProp(k, { type: 'i32' })
return obj
}()
DllCall(..., RECT, ...)
}
A property of type int* would not return the int value; it would return an int*. How would you get the pointer value if it was automatically dereferenced?
What do you mean by "current solution" or "impossible"? What would you have in mind instead?The current solution also makes it impossible for pointer types to be used as arrays, like p[0], p[1].
Yes, it can be done that way.
Code: Select all
#Requires AutoHotkey v2.1-alpha.9
class RECT extends Struct {
left: i32, top: i32, right: i32, bottom: i32
}
PRECT1 := PointerTo(RECT)
PRECT2 := PointerTo2(RECT)
r1 := DllCall('msvcrt\malloc', 'uptr', 32, PRECT1)
r2 := DllCall('msvcrt\malloc', 'uptr', 32, PRECT2)
DllCall("GetWindowRect", "ptr", WinExist("A"), PRECT1, r1)
DllCall("GetWindowRect", "ptr", WinExist("A"), PRECT2, r2)
MsgBox "r1 = {" r1.left "," r1.top "," r1.right "," r1.bottom "}, type = " Type(r1) "`n"
. "r2 = {" r2[0].left "," r2[0].top "," r2[0].right "," r2[0].bottom "}, type = " Type(r2) ""
r11 := r1[1]
r21 := r2[1]
DllCall("msvcrt\free", PRECT1, r1)
DllCall("msvcrt\free", PRECT2, r2)
class Struct {
static __new() {
if this != Struct
Throw
this.Prototype.DefineProp('Ptr', { get: ObjGetDataPtr })
this.Prototype.DefineProp('Size', { get: ObjGetDataSize })
this.DeleteProp('__new')
this.DefineProp('at', { call: StructFromPtr })
}
static Size => this.Prototype.Size
static Size(obj) => ObjGetDataSize(obj.Prototype ?? obj)
static Pointer => (this.DefineProp('Pointer', { value: c := PointerTo(this) }), c)
__Set(name, args, value) {
if args.Length
return this.%name%[args*]
Throw PropertyError('This value of type "' Type(this) '" has no property named "' name '".', -1)
}
}
PointerTo(structClass) {
static cache := Map()
if c := cache[structClass] ?? false
return c
if !ObjGetDataSize(structClass.Prototype)
Throw TypeError("Invalid class", -1)
c := Class(Object)
c.Prototype.cls := structClass
c.Prototype.DefineProp('Ptr', { type: 'uptr' })
c.Prototype.DefineProp('__value', {
get: (this) => this.ptr && StructFromPtr(this.cls, this.ptr).DefineProp('__item', {
get: (this, index) {
if !index
return this
obj := { base: this.base }
ObjSetDataPtr(obj, this.ptr + index * ObjGetDataSize(this))
return obj
}
}),
set: (this, value) {
if value is Integer
this.ptr := value
else if value is this.cls
this.ptr := value.ptr
else
Throw TypeError("Expected a " this.cls.Prototype.__class " or Integer; received a " Type(value), -1)
}
})
cache[structClass] := c
return c
}
PointerTo2(structClass) {
static cache := Map()
if c := cache[structClass] ?? false
return c
if !ObjGetDataSize(structClass.Prototype)
Throw TypeError("Invalid class", -1)
c := Class(structClass.Prototype.__class '*', Object)
c.Prototype.cls := structClass
c.Prototype.DefineProp('Ptr', { type: 'uptr' })
c.Prototype.DefineProp('__value', {
set: (this, value) {
if value is Integer
this.ptr := value
else if this.base == value.base || value is this.cls
this.ptr := value.ptr
else
Throw TypeError("Expected a " this.__class " or " this.cls.Prototype.__class " or Integer; received a " Type(value), -1)
}
})
c.Prototype.DefineProp('__item', {
get: (this, index) {
if !ptr := this.ptr
Throw ValueError("null pointer")
if index
ptr += index * this.cls.size
return StructFromPtr(this.cls, ptr)
}
})
cache[structClass] := c
return c
}