Pointer to object property? Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
RaptorX
Posts: 378
Joined: 06 Dec 2014, 14:27
Contact:

Pointer to object property?

Post by RaptorX » 28 Jun 2022, 07:11

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 ?
Projects:
AHK-ToolKit

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Pointer to object property?

Post by Helgef » 28 Jun 2022, 11:03

This was replaced by (better) :arrow: buffer. Example,

Code: Select all

o := {}
o.p2 := buffer(...)
ptr := o.p2.ptr
Actually retrieving the address ( :arrow: .ptr) is rarely needed, see :arrow: Buffer-like Objects.

Cheers.

User avatar
RaptorX
Posts: 378
Joined: 06 Dec 2014, 14:27
Contact:

Re: Pointer to object property?

Post by RaptorX » 28 Jun 2022, 11:28

Helgef wrote:
28 Jun 2022, 11:03
This was replaced by (better) :arrow: 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 :cry::

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
	}

}
Projects:
AHK-ToolKit

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Pointer to object property?  Topic is solved

Post by Helgef » 28 Jun 2022, 12:15

Assuming the dllcall only outputs,

Code: Select all

this.hDatabase := buffer(a_ptrsize)
dllcall 'ptr', this.hDatabase
hDatabase := numget(this.hDatabase, 'ptr')
Cheers.

User avatar
RaptorX
Posts: 378
Joined: 06 Dec 2014, 14:27
Contact:

Re: Pointer to object property?

Post by RaptorX » 28 Jun 2022, 18:16

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)
Projects:
AHK-ToolKit

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Pointer to object property?

Post by Helgef » 29 Jun 2022, 03:33

Consider not using static then.

User avatar
RaptorX
Posts: 378
Joined: 06 Dec 2014, 14:27
Contact:

Re: Pointer to object property?

Post by RaptorX » 30 Jun 2022, 07:41

Yes, just learned that static functions would not be able to access instance variables. I will be using modifying the code accordingly.
Projects:
AHK-ToolKit

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Pointer to object property?

Post by lexikos » 01 Jul 2022, 03:05

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.

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Pointer to object property?

Post by lexikos » 01 Jul 2022, 03:29

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.)

Post Reply

Return to “Ask for Help (v2)”