COM object: Get double by ref from COM method

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
hotkeyguy
Posts: 170
Joined: 11 Oct 2014, 12:22

COM object: Get double by ref from COM method

18 Apr 2021, 15:47

Hello,

want to get an double dNumber by ref.
Tried the following without success. My assumption is that COM doubles are 8 bytes long:
VarSetCapacity( dNumber, 8, 0 )
; VT_R8 := 5 ; 64-bit floating-point number
; VT_BYREF := 0x4000 ; Pointer to another type of value
dNumberRef := ComObject( 5 + 0x4000, &dNumber) ;

MyComObject.MyComMethod( dNumberRef )



Many thanks and greetings
hotkeyguy
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: COM object: Get double by ref from COM method

18 Apr 2021, 15:58

MyComObject.MyComMethod( dNumberRef[] )
hotkeyguy
Posts: 170
Joined: 11 Oct 2014, 12:22

Re: COM object: Get double by ref from COM method

19 Apr 2021, 06:52

Many thanks swagfag! No error messages, but I get no usefull numeric value back. Tried:
MyComObject.MyComMethod( dNumberRef[] )
dNumberRet := dNumberRef[] ; result is 0

Why is the result not in dNumber?


And must I free something at the end of my code?
hotkeyguy
Posts: 170
Joined: 11 Oct 2014, 12:22

Re: COM object: Get double by ref from COM method

19 Apr 2021, 09:28

I was able to get the value with that example:
ComObjActive() - Syntax & Usage | AutoHotkey with
... := ComVar( 5 ) ; VT_R8 := 5, 64-bit floating-point number
but I don't understand why that's so complicated compared to my first approach!

Any hints are highly appreciated!
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: COM object: Get double by ref from COM method

26 Apr 2021, 03:02

I don't know about "so complicated", but ComVar is longer than your solution because it is old code written as a generic solution to fit all variant types. It uses a ComObjArray to handle conversion of values because it was written before support was added for getting/setting the value of a VT_BYREF ComObject. (Edit: Actually, ComObjArray handles freeing the value without you having to worry about the variant type, whereas the v2 version below doesn't free the value at all. Oops.) You may compare it to the class in the v2 documentation (for v2.0-a133+):

Code: Select all

class ComVar {
    __new(Type := 0xC) {
        ; Allocate memory for the typed variable.
        ; The largest supported type is VT_VARIANT on x64 (24 bytes).
        this.var := Buffer(24, 0)
        ; Create an object which can be used to pass the variable ByRef.
        this.ref := ComValue(0x4000|Type, this.var.ptr + (Type=0xC ? 0 : 8))
    }
    __item {
        get => this.ref[]
        set => this.ref[] := value
    }
}
For your original code, you just need to use dNumberRef[] to retrieve the value after calling the method. Don't use [] when passing the object to a COM method; that defeats the purpose by passing only the current value, not the reference.

The result is in dNumber, but dNumber is considered to contain a string because you've used &address-of. You get a string with the raw bytes of a floating-point number. You can retrieve the number from dNumber with NumGet.

After you use VarSetCapacity, you don't need to explicitly free the variable. If it is a local variable, it will be freed when the function returns, if it can be. Usually an allocation of 8 bytes would be of a permanent type that is reused every time you call the function. Having code included in the script to free it would defeat the purpose, because that could would take more than 8 bytes. ;)
Last edited by lexikos on 26 Apr 2021, 03:31, edited 1 time in total.
Reason: be free!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: mikeyww, WAZAAAAA and 399 guests