Buffer objects support in Numput [beta.9]

Propose new features and changes
User avatar
RaptorX
Posts: 395
Joined: 06 Dec 2014, 14:27
Contact:

Buffer objects support in Numput [beta.9]

17 Sep 2022, 21:57

I was just doing some DLL calls and while following the MSDN documentation I came up with the following code:

Code: Select all

; RGBQUAD structure
; https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-rgbquad
bmiColors := Buffer(4, 0)

; BITMAPINFOHEADER structure
; https://learn.microsoft.com/en-us/previous-versions/dd183376(v=vs.85)
NumPut "uint"  , 40,    ; DWORD biSize;
       "uint"  , 1920,  ; LONG  biWidth;
       "uint"  , 1080,  ; LONG  biHeight;
       "Ushort", 1,     ; WORD  biPlanes;
       "Ushort", 32,    ; WORD  biBitCount;
       "uint"  , 0,     ; DWORD biCompression;
       "uint"  , 0,     ; DWORD biSizeImage;
       "uint"  , 0,     ; LONG  biXPelsPerMeter;
       "uint"  , 0,     ; LONG  biYPelsPerMeter;
       "uint"  , 0,     ; DWORD biClrUsed;
       "uint"  , 0,     ; DWORD biClrImportant;
        bmiHeader := Buffer(4*10)

; BITMAPINFO structure
; https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfo
NumPut "ptr", bmiHeader, ; BITMAPINFOHEADER bmiHeader;
       "ptr", bmiColors, ; RGBQUAD          bmiColors[1];
	    bmi := Buffer(44, 0)
I was promptly slapped with an invalid parameter error and was a bit baffled because if the type parameter is similar to DllCall (as per the documentation) then:
If an object is passed to a Ptr parameter, the value of the object's Ptr property is used.
Not only that, but I quickly learned that even passing the Buffer.Ptr didnt actually copy the objects content to that address but instead just placed the Buffer.Ptr value to that address. :(

I wish Numput would support receiving a buffer-like object and just copy the values as they are into the target to have a more intuitive way of filling out structures as seen in MSDN.

You can see the solution to this problem by clicking below
Spoiler
Last edited by RaptorX on 18 Sep 2022, 07:34, edited 1 time in total.
Projects:
AHK-ToolKit
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: Buffer objects support in Numput [beta.9]

18 Sep 2022, 00:48

Not only that, but I quickly learned that even passing the Buffer.Ptr didnt actually copy the objects content to that address but instead just placed the Buffer.Ptr value to that address.
NumPut puts numbers, and Buffer.Ptr is just a number. Why would it ever copy the contents of the buffer? DllCall doesn't do that either, even when you pass the Buffer itself. It just passes Buffer.Ptr to the function. "Ptr" represents a 32-bit or 64-bit integer, not an entire structure.

If you have bmi1 and bmi2, do you think that NumPut("ptr", bmi1, bmi2) would copy one struct to the other?

Allowing .Ptr to be omitted would be a minor convenience, and might have been more of a hindrance than a help in your case.
I just found that the solution proposed below wont work because it seems like NumPut has a limit as to how many parameters it can take (not documented).
No, you're trying to put 48 bytes of data into a Buffer that has a capacity of 44 bytes.
User avatar
RaptorX
Posts: 395
Joined: 06 Dec 2014, 14:27
Contact:

Re: Buffer objects support in Numput [beta.9]

18 Sep 2022, 07:30

lexikos wrote:
18 Sep 2022, 00:48
NumPut puts numbers, and Buffer.Ptr is just a number. Why would it ever copy the contents of the buffer? DllCall doesn't do that either, even when you pass the Buffer itself. It just passes Buffer.Ptr to the function. "Ptr" represents a 32-bit or 64-bit integer, not an entire structure.
Yes I quickly realized that. Not sure why I instinctively tried to use numput to "copy" one buffer to another.

My mind went like: if I can fill this struct using Numput, I could fill this other struct using Numput as well even though what is used to fill it are other structs. Then realized the obviousness of my mistake in that Buffers are not Numbers :D
lexikos wrote:
18 Sep 2022, 00:48
If you have bmi1 and bmi2, do you think that NumPut("ptr", bmi1, bmi2) would copy one struct to the other?
Actually I instinctively thought that because I was filling structures with Numput and it made sense that all the numbers in a buffer would be put in the target buffers locations.

While the name Numput doesn't imply it, it kind of made sense to me.
The proposed idea sounds like:

If arg is a number
Get this number and put it in this targets memory block

If arg is a buffer and type is "struct" or "copy" (maybe)?
Get all these numbers and put them in the targets memory block

Unfortunately I don't think there is a built in function to do that atm and while struct support is way better in v2 it just needs a little push to be awesome.
lexikos wrote:
18 Sep 2022, 00:48
Allowing .Ptr to be omitted would be a minor convenience, and might have been more of a hindrance than a help in your case.
Totally agree... It would have been a bit more problematic to find the issue for sure.
lexikos wrote:
18 Sep 2022, 00:48
No, you're trying to put 48 bytes of data into a Buffer that has a capacity of 44 bytes.
Oh man, of course you are right. For whatever reason I thought ushort was the one to be used for BYTE. I think I should use char instead

The day we could use some of the most basic/common MSND types in dllcall/numput/numget instead of translating them, that's the day dllcall will make sense to a LOT of people.
Projects:
AHK-ToolKit

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 23 guests