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
COM object: Get double by ref from COM method
Re: COM object: Get double by ref from COM method
MyComObject.MyComMethod( dNumberRef[] )
Re: COM object: Get double by ref from COM method
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?
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?
Re: COM object: Get double by ref from COM method
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!
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!
Re: COM object: Get double by ref from COM method
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+):
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.
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
}
}
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!
Reason: be free!