Code: Select all
t := TestClass()
msgbox "size: " t.size "`n"
. "ptr: " t.ptr " / " t.buf.ptr " (equal: " (t.ptr = t.buf.ptr) ")"
class TestClass {
__New(ptr:=0) {
Static size := 8
f := {size:{t:"UInt", o:0}, field2:{t:"UInt", o:4}} ; field data (type and offset)
; ============================================================================
; 1) size IS NOT initialized, ptr MISMATCH = doesn't work
; ============================================================================
this.DefineProp("buf", {Get:(o) => (ptr ? {ptr:ptr,size:size} : Buffer(size,0))})
this.DefineProp("ptr", {Get:(o) => this.buf.ptr})
; ============================================================================
; 2) size IS initialized, ptr MISMATCH = works / unsafe
; ============================================================================
; this.DefineProp("buf", {Get:(o) => (ptr ? {ptr:ptr,size:size} : Buffer(8,0))})
; this.DefineProp("ptr", {Value:this.buf.ptr})
; ============================================================================
; 3) size IS initialized, ptr MATCH = works / safe
; ============================================================================
; this.DefineProp("buf", {Value: (ptr ? {ptr:ptr,size:size} : Buffer(8,0))})
; this.DefineProp("ptr", {Get:(o) => this.buf.ptr})
; ============================================================================
; 4) size IS initialized, ptr MATCH = works / safe
; ============================================================================
; this.DefineProp("buf", {Value: (ptr ? {ptr:ptr,size:size} : Buffer(8,0))})
; this.DefineProp("ptr", {Value:this.buf.ptr})
; ============================================================================
this.DefineProp("f" , {Get:(o) => f}) ; to access field data (type and offset)
this.size := size ; init the size property
}
__Get(name,p) => NumGet(this.ptr, this.f.%name%.o, this.f.%name%.t)
__Set(name,p,value) => NumPut(this.f.%name%.t, value, this.ptr, this.f.%name%.o)
}
I usually map the buffer to the buf property, and the ptr of the buf separately to the ptr property. The strangeness comes with using {Get:...} or {Value:...} as the descriptor.
I usually try to use {Get:...} in order to ensure a property is read only, as a built-in means to make sure the user can't use the object other than intended. But it seems that when using a buffer I must use {Value:...}, otherwise the reported ptr of the buffer is actually wrong when I map the ptr property.
I hope this isn't too obscure. I tried to map it out as clearly as possible.
So I know what I need to do to "make it work". Basically options #3 and #4 above work fine. And the key is to ensure that the buf property is mapped with {Value:...} instead of {Get:...}.
But I'm wondering if this might be a bug? Or did I miss something in the docs that explains the mismatched ptr when using options #1 and #2?
Thanks for any explanation on this matter. I've been chasing this issue for a while and have finally narrowed it down to a smaller case that is easy to replicate.