Binary Data | VarSetCapacity | VarSetLength | Heap Object

Discuss the future of the AutoHotkey language
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Binary Data | VarSetCapacity | VarSetLength | Heap Object

29 Jun 2018, 19:03

I create this topic to discuss how AutoHotkey will use the memory and binary data.
I have read Thoughts for v2.0, Binary Data section, but not many details are given, and I have several doubts.

Currently this works as it should:

Code: Select all

str := f()
MsgBox str      ; Hello    ; OK
NumPut(32, &str+10, "UChar")    ; 32 = SPACE
MsgBox str    ; Hello world!    ; OK

f()
{
    str := "Hello world!"
    NumPut(0, &str+10, "UChar")
    MsgBox str    ; Hello    ; OK
    return str
}
But this one doesn't:

Code: Select all

Buffer := f()
MsgBox NumGet(&Buffer+10, "UChar")    ; 0    ; WRONG

f()
{
    local Buffer := ""
    VarSetCapacity(Buffer, 100, 0)
    NumPut(255, &Buffer+10, "UChar")
    MsgBox NumGet(&Buffer+10, "UChar")    ; 255    ; OK
    return Buffer
}
I imagine that with the addition of VarSetLength, it would work correctly. But I have doubts, in the documentation is not explained anywhere in detail how AutoHotkey handles the use of memory. How would this work exactly?.
lexikos: I would like to know what you have in mind and how this would affect the Scripts currently. It would be interesting to keep in mind when writing scripts for v2. If you are still not sure, we can discuss it right here.

I emphasize the use of binary data because I think it would be one of the most significant things that it will affect the majority of scripts currently written for v2. I think we should give high priority to this before anything else.

If VarSetLength is implemented, VarSetCapacity will accept the length of the string in characters, instead of bytes as it does now:
  • VarSetCapacity will be used only to improve performance when using strings (optimise gradual concatenation). My question: Can it also be used in DllCalls when a string is to be stored?.
  • If VarSetCapacity is going to be used only with strings, does it make sense to keep the FillByte parameter?.
  • Should we add a parameter to VarSetCapacity to specify the encoding? (VarSetCapacity(TargetVar, Characters, Encoding:="UTF-16")).
The problem with VarSetCapacity is currently as follows:
  • The memory is not completely released. We do not have an efficient memory management.
  • https://lexikos.github.io/v2/docs/commands/VarSetCapacity.htm wrote:this function is often called simply to ensure the variable has a certain minimum capacity
    If we are going to reserve memory for a structure, obviously we want to have the exact amount of memory that we specify, and not "at least". What is wrong with reserving a few more bytes ?, Simple, we can not use VarSetCapacity as a sizeof, and some structures require that in its first member we specify its size, this must be exact, so we are forced to store the size in a separate variable (for example). Also, why reserve more memory if we are not going to use it?.

I would like to propose, instead of VarSetLength, a Heap Object. The name of the function would be HeapCreate, for consistency with GuiCreate and MenuCreate.
The Heap object would look something like this: https://github.com/flipeador/AutoHotkey ... m/Heap.ahk.
Reasons:
  • Greater handling and ease when recovering the reserved memory size, changing the size, etc.
  • We can pass the object to a function (or return it) without having to copy the binary data.
  • We can incorporate several methods to copy from/to without having several functions. This is normal when working with binary data, for example files or structures.
  • [new] We could also have the ReadNum and WriteNum methods as FileObject. NumGet(&struct+Offset, "Int64")/NumPut(0, &struct+Offset, "Int64") => HeapObj.ReadInt64(Offset)/HeapObj.WriteInt64(Offset).

Code: Select all

Heap := HeapCreate()
Heap.Alloc(1024)    ; set capacity
Heap := ""    ; release it

Obj := { Buffer: HeapCreate().Alloc(1024) }
MsgBox Obj.Buffer.Length    ; (or .size) 1024

In addition to all this, it would be interesting to remove ObjGetAddress, and be able to use &Obj.String and VarSetCapacity(Obj.String, 1024).

:wave:
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 00:54

I think the idea is good.
Especially if we remove the normal VarSetCapacity.
And it's even better if we give it the same methods as the file object and remove NumPut & NumGet along the way.
Also add a built in _Structs instead of having NumPut/NumGet do the work.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 06:03

Hello, I am interested in this topic too, I like many of both of your suggestions.
The memory is not completely released
You can realease it with varsetcapacity x, 0, not releasing (small buffers) automatically, implies a gain in (speed) performance. If memory objects were to be implemented, they would need to perform similarly well to varsetcapacity, typical example to consider,

Code: Select all

f(x){
	varsetcapacity var, 64	; allocates on first call only
	numput x, var
	dllcall 'fn', 'ptr', &var
}
g(x){
	m := memCreate(64)	; creates an object and allocates on each call?
	m.writeuptr(x, 0)
	dllcall 'fn', 'ptr', m.getaddress()
}
I'm not sure that is easily achievable. Another issue with the current use of varsetcapacity is that, type x, where x comes from varsetcapacity x, y, returns 'String', a separate type would be much preferable imo. I prefer memory/binary type objects for clarity and convenience, but performance is important too, and custom classes can be used for it already.

Brainstorming, not complete.
Perhaps a simpler alternative would be to leave varsetcapacity as is, but flag the output variable as a Binary type and remove the -1 option, the RequestedCapacity would be set exactly as asked for. Then add strSetLength strOut, Length, where strOut is of type String. If Length is greater than strOut's current length, strOut's string buffer is reallocated, if Length is less or equal to the current length, the internal string length is updated to Length and zero terminated. If length is omitted, the zero terminator is searched for as currently varsetcapacity x, -1 does. strSetLength str, -1 could release the string as varsetcapacity str, 0 currently does. strGetLength str would return the string buffer's length, as varSetCapacity str currently does. In addition, I think varGetCapacity x would be appropriate and it should be exactly what the user asked for. var/str-GetCapacity x:=1 would be an error. The capacity of number type variables should be documented as 8 bytes and then there is never a reason to ask for it. Having separate string and binary types would also mean that str == bin would be an error and strA == strB would do memCmp only up to strlen(strA) if equal to strlen(strB). binA == binB would behave as it does now.

In short, the main features I miss, is being able to set the internally stored string length, distinguish between string and binary types, and set and retrieve exact size for binary buffers. (I think :lol: )
In addition to all this, it would be interesting to remove ObjGetAddress, and be able to use &Obj.String [...]
Unfortunately, you now can do &Obj.String, which will cause great problems for all the learn-by-testing-rather-than-read-the-manual coders, I see no reason to allow it to be a problem in the first place.
[...] and VarSetCapacity(Obj.String, 1024).
:o ;)

Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 06:43

The most positive thing I can say about the current implementation of binary data in AHK is "working problematic inconsistent ugly hack".

Binary is a data type.
Its own data type which is very basic.
It is seperate from strings, objects, integers and floats.
Yet it is married to strings which seems just completely random.
We still use the same binary type that AHK Basic used and it feels like only minor enhancements happened.
However we are far from anything thats good for everyday use.
Whatever we do it is better to remove anything we have right now. We will only limit ourselves for future development if we realease any version containing the current binaries.
We can always add the old binaries again at a later date or better come up with something useable.
However once this trash is inside it's inside.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 06:54

- I think the ideas are potentially interesting. although they are not something I need AFAICS at present. I would first consider looking at things more simply. These are my main concerns:
- Being able to store binary data as values in objects just like strings.
- Some kind of SizeOf function (size in bytes), cf. the StrLen function (size in 2 or 1 byte units based on A_IsUnicode, AFAIK this unit size would always be 2 in AHK v2).
- A_WA(/A_AW) and A_CharWidth(/A_CharSize), W or A, 2 or 1. Such variables would still be useful in AHK v1/v2 even if AHK v2 was Unicode-only. These are verbose and ugly:

Code: Select all

A_IsUnicode?"W":"A"
A_IsUnicode?2:1
1+!!A_IsUnicode
vChars << !!A_IsUnicode
- A MemCopy function, to copy binary data from one location to another.
- What would a 'Binary' (or 'Bin') type be? I suppose than in AHK ANSI it would be any data containing null bytes. And in AHK Unicode it would be any data containing 2-byte null characters at even offsets. So anything that would return true for InStr(vText, Chr(0)).
- Or instead, you might like to say that any string or piece of binary data, should be able to be regarded as a string or piece of binary data (whether it contains nulls or not), especially for when variable comparisons are done, so you'd want some sort of TypeSet function to set String/Binary.
- Should there be `0 for Chr(0)?
- A function to search binary data for specific bytes, e.g. to check if data contains a null byte.

- My possible views on set size/capacity functions:
conversion logic, v1 = -> v1 := -> v2, two-way compatibility - Page 7 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 16#p215816

Code: Select all

VarSetLen(Var, Size, FillByte) ;[bytes] [or 'VarSetSize']
VarSetCapacity(Var, Capacity, FillByte) ;[bytes] [as it is now]
StrSetLen(Var, Len, FillChar) ;[chars]
StrSetCapacity(Var, Capacity, FillChar) ;[chars]
- Re. 'learn-by-testing-rather-than-read-the-manual coders'.
- Some programs/situations don't even have manuals.
- People tend to go off-piste because the manual is non-existent, unclear, or to confirm what they believe the unclear manual says.

- What is this obsession with removing functions? Are those comments seriously meant?
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 07:08

What is this obsession with removing functions? Are those comments seriously meant?
What is that obsession to maintain thousands of functions that do the same or similar things that could be "optimized" in a class or only in a function?.
If there is something I do not like about ahk_h it is the amount of unnecessary functions that it has, horrible. I believe that AHK should provide only the main and most useful/common functionality. A good handling of the memory and binary data is something necessary.
The current implementation, as nnnik says, is disastrous.
Please, do not mix other versions of AHK in this topic. This is only for AHKv2, not things like two-way compatibility stuff. Let's try not to divert this topic.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 07:14

nnnik wrote:And it's even better if we give it the same methods as the file object and remove NumPut & NumGet along the way
NumPut and NumGet should be maintained, otherwise how would we write in memory when it is not a Heap Object?. Of course, we can remove the Offset parameter once and for all.
Helgef wrote:You can realease it with varsetcapacity x, 0, not releasing (small buffers) automatically, implies a gain in (speed) performance. If memory objects were to be implemented, they would need to perform similarly well to varsetcapacity, typical example to consider
Yes, you're right. Honestly I can not talk much about this because I never set out to see the source code completely, so I have no idea how much work this would imply and how it would affect performance. :problem:
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 07:27

NumPut and NumGet should be maintained, otherwise how would we write in memory when it is not a Heap Object?. Of course, we can remove the Offset parameter once and for all.
I disagree - a BinaryObject (currently the file object is a stream) should have several possible sources.
Allocating the memory using AHK should just be 1 option. A different option should be creating such an object from a ptr+size.

Yes jeeswg these comments are seriously meant. Im wondering if your comments are actually serious.
Recommends AHK Studio
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 07:54

nnnik wrote:I disagree - a BinaryObject (currently the file object is a stream) should have several possible sources.
Allocating the memory using AHK should just be 1 option. A different option should be creating such an object from a ptr+size.
I'm not sure what you mean, I'd like to see an example. Anyway, it does not sound bad.

I do not know how AHK asks the system for memory, but I think using Windows Heap functions provides better functionality (and native). I agree that the binary data must have its own type.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 08:22

Please, do not mix other versions of AHK in this topic. This is only for AHKv2, not things like two-way compatibility stuff. Let's try not to divert this topic.
:thumbup:
I disagree - a BinaryObject (currently the file object is a stream) should have several possible sources.
Allocating the memory using AHK should just be 1 option. A different option should be creating such an object from a ptr+size.
Yes, similar to the 'h' option for fileOpen.

Cheers.
Spoiler
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 09:15

e.g.:

Code: Select all

streamObject := MemoryAllocate(size,accessMode)
streamObject := fileOpen(fileName, accessMode)
streamObject := streamOpen(pointer,size,accessMode)
Should all result in an object supporting the same interface.
I would also like to propose to include a seperate binary type - the struct:
It should be similar to HotkeyIts but I would prefer not having to put the struct inside a string:

Code: Select all

struct RECT {
int x,y,w,h;
}
actualRect := new RECT()
Combinations of the stream object and the rect object:

Code: Select all

actualStream := streamObject.readStruct(RECT)
streamObject.writeStruct(RECT,actualStream)
Both & DllCall:

Code: Select all

DllCall(anyFunc
	,RECT,actualRect ;passes a pointer of the actual struct
	,Ptr(RECT),actualRect ;passes a pointer of the pointer of the actual struct
	) ;neither need initialization and upon return they will be accessible structs
DllCall(anyFunc
	,"bin",streamObject ;passes the pointer of the binary of the streamObject
	,"bin*",streamObject ;passes the pointer of the pointer of the binary of the streamObject
	,"Ptr",&streamObject ;a cause of errors - this will not give the pointer of the binary - instead it will give the pointer of the Object (consistent with other objects)
	,"Ptr*",&streamObject ;this should probably cause an exception
	,"Ptr",streamObject ;just like this
	) ;neither need initialization however the size is undefined. - could be fixed via setSize()
Recommends AHK Studio
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 10:01

I prefer to keep it "simple" and not add more data types.
,"bin",streamObject => ,"uptr",streamObject.ptr.
,"bin*",streamObject => ,"uptrp",streamObject.ptr.
For the rest it seems fine.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 10:40

Flipeador wrote:I prefer to keep it "simple" and not add more data types.
,"bin",streamObject => ,"uptr",streamObject.ptr.
,"bin*",streamObject => ,"uptrp",streamObject.ptr.
For the rest it seems fine.
However that requires initialization:

Code: Select all

streamObject := streamOpen(accessMode := "rw")
...,"uptrp",streamObject.ptr...
So I wouldn't call it simpler.
Recommends AHK Studio
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 10:48

What exactly is the accessMode parameter for?. In FileObject it makes sense because sometimes the file is blocked for certain accesses; But for the memory object why?.
streamObject := streamOpen(accessMode := "rw"): What are you opening exactly here?.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 11:31

Flipeador wrote:What exactly is the accessMode parameter for?. In FileObject it makes sense because sometimes the file is blocked for certain accesses; But for the memory object why?.
You know that binary data may be read only?
streamObject := streamOpen(accessMode := "rw"): What are you opening exactly here?.
Im creating a stream with no assigned pointer that can be written to and read from.
The pointer will be assigned by the DllCall. e.g:

Code: Select all

DllCall("gdip\GdipCreateSolidFill"
,"UInt", 0 ;the color black
,"Ptr*",i) ;this is the same as:
VarSetCapacity(iPtr,A_PtrSize)
DllCall("gdip\GdipCreateSolidFill"
,"UInt", 0 ;the color black
,"Ptr", &iPtr)
i := NumGet(&iPtr,"Ptr")
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

30 Jun 2018, 13:09

nnnik wrote:

Code: Select all

struct RECT {
int x,y,w,h;
}
actualRect := new RECT()
I like this very much, and many of your other ideas too. However, I guess the chances are low.

Speculations.
For those who didn't notice, the new string function, calls an object's toString method when it recieves an object. This might give an indication of future support for objects to be passed as variables and used in expressions, which will make some of your ideas more feasible to implement as custom classes. For example, it is reasonable that obj . 'abc' would eventually be equivalent to obj.toString() . 'abc' and maybe obj + 1 to be equivalent to obj.toNumber() + 1, and similarily, an object passed to dllcall (or any built-in function) could also support something like that, so, eg, dllcall 'fn', 'ptr', obj would be equivalent to dllcall 'fn', 'ptr', obj.toString() or maybe even dllcall 'fn', 'ptr', obj.toNumber('ptr').

Cheers.
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

01 Jul 2018, 04:30

I had already come to the conclusion that a dedicated binary/buffer type or object would be better than VarSetCapacity/VarSetLength, but hadn't written about it in v2-thoughts (mostly due to lack of interest/motivation).

For reference, JavaScript has ArrayBuffer, DataView and various typed arrays.
The memory is not completely released. We do not have an efficient memory management. [...] Also, why reserve more memory if we are not going to use it?
In some cases, small allocations are made which cannot be freed. (These allocations are made with SimpleHeap::Malloc, which is a custom function.) This apparently reduces average memory usage, rather than increasing it, since it totally avoids the book-keeping overhead needed for proper heap allocations. This is actually why the memory cannot be freed. It is also faster, since most allocations are just a matter of incrementing a pointer (and sometimes the allocation can be avoided entirely). More memory might be allocated than initially needed, but all of the additional space within that block is available for use by the script.

In order to guarantee that VarSetCapacity sets exactly the capacity you expect, it would potentially have to free (or throw away) a previous allocation which was already sufficiently large. That wastes time. You can force it by first ensuring the variable has normal heap (not SimpleHeap) memory:

Code: Select all

VarSetCapacity(buf, 2)
MsgBox VarSetCapacity(buf) ; 6
VarSetCapacity(buf, 0)
MsgBox VarSetCapacity(buf) ; still 6
VarSetCapacity(buf, 128)
VarSetCapacity(buf, 0)
MsgBox VarSetCapacity(buf) ; 0
VarSetCapacity(buf, 2)
MsgBox VarSetCapacity(buf) ; 2
However, you still can't allocate an odd number of bytes.
In addition to all this, it would be interesting to remove ObjGetAddress, and be able to use &Obj.String and VarSetCapacity(Obj.String, 1024).
I'm not sure how you think that would be achieved. Is Obj.String in this case merely containing a string, or a buffer/binary-data object? VarSetCapacity requires a variable reference, but Obj.String is not a variable; it returns a value.
And it's even better if we give it the same methods as the file object and remove NumPut & NumGet along the way.
NumPut and NumGet are used with arbitrary memory addresses, not just offsets within buffers allocated by the script itself. For instance, NumGet is used in combination with DllCall to call functions retrieved from the v-table of a non-IDispatch COM object. Supposing that one uses built-in struct support to do the same thing, one must first initialize a "struct object" from the object itself, then retrieve a "struct object" encapsulating the v-table. The code would be longer and slower. Even if both structs and v-tables are supported natively, they may not cover all possible uses of NumPut/NumGet, let alone in an optimal way. NumPut/NumGet is a very low-cost, high-power feature, and best of all, it has already been developed and highly tested.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

01 Jul 2018, 05:04

NumPut/NumGet is a very low-cost, high-power feature, and best of all, it has already been developed and highly tested.
And generally found to be unwieldy and insufficient when it comes to difficult structs.
Structs dont replace NumPut and NumGet - they are a handy extension that covers 90% of all their use cases.
Structs and Streams both replace numGet and numPut. As far as I understand the v-table is more of a stream with pointers inside.
If it is retrieved by DllCall and the suggestion follows my original implementation it should be something similar to:

Code: Select all

bin := DllCall("whatever", "bin")
bin.seek(3*A_PtrSize)
DllCall(bin.ReadUPtr()
The only additional line comes from the seek - so it might be better to provide an alternative that makes specifying an optional offset to the current offset easier.
Correct me if Im wrong on anything.
Recommends AHK Studio
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

07 Jul 2018, 01:04

And generally found to be unwieldy and insufficient when it comes to difficult structs.
My point was that I won't remove NumGet/NumPut, regardless of whether structs are supported natively, hence "Even if both structs and v-tables are supported natively".
Structs and Streams both replace numGet and numPut.
Structs, streams and NumGet/NumPut can all be used to the same effects, but each has tasks it is suitable for and others that it is not. Similarly, DllCall can be used to implement NumGet/NumPut (and was used for that purpose in the past), yet NumGet and NumPut do not replace DllCall.
If it is retrieved by DllCall and the suggestion follows my original implementation it should be something similar to:
I do not think representing a COM interface as a stream makes any sense. Streams are naturally read or written sequentially, but a v-table requires frequent random access at known offsets.

The COM object pointer is typically returned by ComObjCreate or ComObjQuery, less frequently by DllCall, and even then, generally as an output parameter, not as a return value. Finding the function address to call requires a multiple level dereference (first at offset 0 to get the v-table address, then at an offset within the v-table), which would mean two binary/stream objects just to call a function once. This makes the "stream" abstraction "unwieldy" and unsuitable for this purpose.

A more suitable shortcut would be comobj[Offset](Type1, Arg1, Type2, Arg2, RetType) or similar, where comobj is a ComObject of variant type VT_UNKNOWN (wrapping an IUnknown interface pointer). The "this" pointer would be included automatically, and the default return type could be HRESULT (translated to an exception on failure). Where the stream abstraction would add overhead in the form of constructing and invoking objects, this shortcut would likely perform even better than the current NumGet-NumGet-DllCall method due to the reduction in script overhead.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Binary Data | VarSetCapacity | VarSetLength | Heap Object

07 Jul 2018, 01:56

Then are you planning on implementing a hard-coded version for every possible struct that is out there?
Regardless I think it looks nice.
Though I want to get back on topic which is how a user would implement a binding to a COM object with an IUnkown Interface with NumGet and with the stream object (or the struct object if it is more suited)

From what I have seen so far people always looked up the vTable whenever they did a call on any of the functions. I always assumed that was due to poor code design (correct me if Im wrong and it is neccessary).
Towards me it makes way more sense to read all the values from the table that you need once and then put them into variables. If all functions are read then the stream object is superior. If the functions read are random then NumGet ius superior.
Regardles it doesn't seem to matter that much.
Recommends AHK Studio

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: lexikos and 33 guests