Page 1 of 1
Pointer to object property?
Posted: 28 Jun 2022, 07:11
by RaptorX
Hi guys!
looking at
this post I noticed that there was at some point a method to get a property's address like this:
myobject.GetAddress("p2").
Is there any equivalent in V2 ?
Re: Pointer to object property?
Posted: 28 Jun 2022, 11:03
by Helgef
This was replaced by (better)
buffer. Example,
Code: Select all
o := {}
o.p2 := buffer(...)
ptr := o.p2.ptr
Actually retrieving the address (
.ptr) is rarely needed, see
Buffer-like Objects.
Cheers.
Re: Pointer to object property?
Posted: 28 Jun 2022, 11:28
by RaptorX
Helgef wrote: ↑28 Jun 2022, 11:03
This was replaced by (better)
buffer. Example,
Code: Select all
o := {}
o.p2 := buffer(...)
ptr := o.p2.ptr
I am doing a very weird thing. It is not extremely important but it got my curiosity.
Here is what Im trying:
Code: Select all
class MyClass
{
; I am doing a series of fat arrow function calls mainly to allow
; the editor to see the functions and parameters but i dont want to define
; each of them separatedly, so I am just calling the same function
; and passing the DLLCall parameters as an array
Open(filename) => MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", &hDatabase:=0, "cdecl int"]*)
static fnCall(fnName, params*) {
fnName := StrLower(StrReplace(fnName, ".Prototype.", "_"))
; in this particular example hDatabase gets written by the call
; so I would like to access hDatabase from Open and fnCall.
; As this is a class I could try and have a class variable to be able
; to access from both methods.
; this solution works but it feels like a hack more than anything
switch fnName {
case "open":
params[4] := &hDatabase:=0
}
result := DllCall(MyClass.dllPath "\" fnName, params*)
; The problem is that hDatabase gets set AFTER the DllCall
; so I have to do this hack here
if hDatabase
this.hDatabase := hDatabase
return result
}
}
This option and setting a global variable work but both feel like a hack.
Im hoping to do something like this:
Code: Select all
class MyClass
{
; passing the address to the objects property so that when the DLLCall
; sets the value it would be already stored in this.hDatabase
Open(filename) => MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", this.&hDatabase:=0, "cdecl int"]*)
; I was hoping to do any option like this
; Open(filename) => MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", &this.hDatabase:=0, "cdecl int"]*)
; Open(filename) => MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", this.getAddress(hDatabase:=0), "cdecl int"]*)
; Open(filename) => MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", strPtr(this.hDatabase:=0), "cdecl int"]*)
static fnCall(fnName, params*) {
fnName := StrLower(StrReplace(fnName, ".Prototype.", "_"))
return DllCall(MyClass.dllPath "\" fnName, params*)
}
}
EDIT:
Just tried this code and it doesnt work
:
Code: Select all
class MyClass
{
static hDatabase := Buffer(8, 0)
Open(filename) {
OutputDebug MyClass.hDatabase.ptr
MyClass.fnCall(A_ThisFunc, ["AStr",filename,"Ptr*", MyClass.hDatabase.ptr, "cdecl int"]*)
}
static fnCall(fnName, params*) {
fnName := StrLower(StrReplace(fnName, ".Prototype.", "_"))
result := DllCall(MyClass.dllPath "\" fnName, params*)
Outputdebug MyClass.hDatabase
return result
}
}
Re: Pointer to object property? Topic is solved
Posted: 28 Jun 2022, 12:15
by Helgef
Assuming the dllcall only outputs,
Code: Select all
this.hDatabase := buffer(a_ptrsize)
dllcall 'ptr', this.hDatabase
hDatabase := numget(this.hDatabase, 'ptr')
Cheers.
Re: Pointer to object property?
Posted: 28 Jun 2022, 18:16
by RaptorX
This actually worked.
Im having a bit of an issue with the this object because it is bringing the class variable instead of the instance variable because the method is static.
Any pointers on that? (no pun intended)
Re: Pointer to object property?
Posted: 29 Jun 2022, 03:33
by Helgef
Consider not using static then.
Re: Pointer to object property?
Posted: 30 Jun 2022, 07:41
by RaptorX
Yes, just learned that static functions would not be able to access instance variables. I will be using modifying the code accordingly.
Re: Pointer to object property?
Posted: 01 Jul 2022, 03:05
by lexikos
RaptorX wrote:static functions would not be able to access instance variables
Sure they can. Did you ever tell your function
which instance you want it to access?
They aren't static
functions, but static
methods. Within a class body,
static means that it is a property of the class. This just gives you one way to reference the function. It doesn't limit what the function can do.
this is just a parameter. You pass it every time you call the method; it's just on the left-hand side of
. instead of inside the parentheses.
How you
call a function defines what it's
this parameter will contain, not how you define the method. When you call
MyClass.fnCall(),
this will be
MyClass. If you called
(MyClass.fnCall)(MyClass()), then
this would be an instance. If you assigned
x.fnCall := MyClass.fnCall and called
x.fnCall() then
this would be
x.
It is no different to any other function - if you don't pass the function an object, it won't have an object.
The point of a static method is generally that it doesn't require or operate upon a given instance of the class. I think there's probably just no reason for you to use
static in this case.
Re: Pointer to object property?
Posted: 01 Jul 2022, 03:29
by lexikos
The best pattern for output parameters of handle or pointer type is generally this:
- Create an object that represents the handle or pointer (perhaps via a class definition).
- Give the object a __delete method which closes the handle, releases the pointer, or whatever.
- Give the object a ptr property with initial value of 0.
- When you call DllCall/ComCall, use "ptr*", obj.
DllCall/ComCall will retrieve the input value (which is ignored in some cases) from
obj.ptr and will
assign the output value to
obj.ptr.
For instance - assuming an instance of
MyClass doesn't itself represent the database (connection?) - you would have
this.Database referring to a database object, instead of a handle. You would then pass
"Ptr*", this.Database to DllCall. It will not assign to
this.Database, but to
this.Database.Ptr. If you have parameters that expect a database handle,
"Ptr", this.Database will pass the value of
this.Database.Ptr.
If MyClass represents a database connection, you can just store the handle in
this.Ptr and pass
this instead of
this.Database.
Ptr can be a dynamic property (with a setter and getter), but there's usually no need. You can, for instance, create an object with a
Ptr setter which really just assigns
this.targetObject.hDatabase := value. You could then use this object in lieu of a VarRef; i.e. create one whenever you need DllCall to assign a pointer to a property. (This only works with
"Ptr*" parameters.)