Passing structure to function

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Passing structure to function

29 Dec 2018, 08:42

I can not pass structure pointer to function:
https://docs.opencv.org/2.4/modules/cor ... reateimage
CreateImage

Creates an image header and allocates the image data.

C: IplImage* cvCreateImage(CvSize size, int depth, int channels)

Python: cv.CreateImage(size, depth, channels) → image
Parameters:

size – Image width and height
depth – Bit depth of image elements. See IplImage for valid depths.
channels – Number of channels per pixel. See IplImage for details. This function only creates images with interleaved channels.
CvSize structure:
int width
int height
https://docs.opencv.org/ref/2.4/da/dcb/ ... vSize.html

Code: Select all

VarSetCapacity(cvsize, 8, 0)
NumPut(100, cvsize, 0, "int")
NumPut(100, cvsize, 4, "int")
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "ptr", &cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
It can be done if I send copy of structure like this:

Code: Select all

width := 100
height := 100
cvsize := (height << 32) | width
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
or pass elements of structure as parameters:

Code: Select all

width := 100
height := 100
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
But autoit successfully sends structure:

Code: Select all

Local $cvsize = DllStructCreate("int;int")
DllStructSetData($cvsize, 1, 100)
DllStructSetData($cvsize, 2, 100)
Local $Result = DllCall("opencv_core2413.dll", "ptr:cdecl", "cvCreateImage" , "struct" , $cvsize , "int" , 8, "int" , 2)
MsgBox("","", $Result[0])
32bit dll here:
https://files.fm/u/6ny65dcr
Last edited by malcev on 29 Dec 2018, 11:56, edited 3 times in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Passing structure to function (bug?)

29 Dec 2018, 09:15

What the function expects is not a pointer to the struct but being passed the struct directly.
In this case you have to use the second version or this:

Code: Select all

width := 100
height := 100
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
Though the order of width and height may be mixed up
Recommends AHK Studio
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Passing structure to function (bug?)

29 Dec 2018, 09:51

would

Code: Select all

VarSetCapacity(cvsize, 8, 0)
NumPut(100, cvsize, 0, "int")
NumPut(100, cvsize, 4, "int")
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
work?
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Passing structure to function (bug?)

29 Dec 2018, 09:57

It should be mentioned that

Code: Select all

msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
will most likely work only for a 32-bit DLL.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Passing structure to function (bug?)

29 Dec 2018, 10:03

- @nnnik: Thanks for giving me the clue to what the issue might be.
- @malcev: This is a common issue with the POINT structure affecting Winapi functions such as: AccessibleObjectFromPoint, ChildWindowFromPoint, WindowFromPoint.
- Instead of passing a pointer to a POINT struct, you pass a value.
- You can use bitshift, bitwise-and and bitwise-or to combine the x and y values into one UInt64 value and pass that.
- [EDIT:] Something like: DllCall("WindowFromPoint", UInt64,(vPosX&0xFFFFFFFF)|(vPosY<<32), Ptr)
- Perhaps you could pass the 2 values as separate Int values, as nnnik pointed out, but it may be that that doesn't work in some situations, possibly in 64-bit.

- Here are some related links, search for: FromPoint.
PixelSearch + PostMessage Click - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 07#p161307
script does not work in 64 bit AHK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 36#p167136
DllCall converter/cleaner (e.g. x32 to x64/x32 two-way compatible) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 11#p173111
jeeswg's documentation extension tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 36#p155736
Wish List 2.0 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 60#p171860
Last edited by jeeswg on 29 Dec 2018, 12:23, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function (bug?)

29 Dec 2018, 11:10

Why Autohotkey can not pass copy of structure directly as it does autoit?
https://www.autoitscript.com/autoit3/do ... llCall.htm
* Add * to the end of another type to pass it by reference. For example "int*" passes a pointer to an "int" type.
May be move this topic to feature request?
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Passing structure to function (Feature Request)

29 Dec 2018, 11:38

malcev wrote:Why Autohotkey can not pass copy of structure directly as it does autoit?
That's exactly what

Code: Select all

DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", ...)
does.

cvCreateImage
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function (Feature Request)

29 Dec 2018, 11:54

Therefore the correct variant to send copy of structure is code by swagfag ?

Code: Select all

VarSetCapacity(cvsize, 8, 0)
NumPut(100, cvsize, 0, "int")
NumPut(100, cvsize, 4, "int")
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Passing structure to function (Feature Request)

29 Dec 2018, 11:58

No! It's

Code: Select all

width := 100
height := 100
cvsize := (height << 32) | width
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError
A structure like

Code: Select all

VarSetCapacity(cvsize, 8, 0)
NumPut(100, cvsize, 0, "int")
NumPut(100, cvsize, 4, "int")
can only be passed by pointer.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function

29 Dec 2018, 12:02

But if I have this structure (4 elements "doubles")?
double d0,
double d1 = 0,
double d2 = 0,
double d3 = 0
Last edited by malcev on 29 Dec 2018, 12:18, edited 3 times in total.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Passing structure to function

29 Dec 2018, 12:07

Most likely, the function will require a structure pointer in this case.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function

29 Dec 2018, 12:25

This code does not work:

Code: Select all

width := 100
height := 100
window := "test"

DllCall("LoadLibrary", "Str", "opencv_core2413.dll", "Ptr")
DllCall("LoadLibrary", "Str", "opencv_highgui2413.dll", "Ptr")

VarSetCapacity(cvsize, 8, 0)
NumPut(width, cvsize, 0, "int")
NumPut(height, cvsize, 4, "int")
pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")

VarSetCapacity(cvScalar, 32, 0)
NumPut(255, cvScalar, 0, "Double")
NumPut(255, cvScalar, 8, "Double")
NumPut(255, cvScalar, 16, "Double")
NumPut(255, cvScalar, 24, "Double")
DllCall("opencv_core2413.dll\cvSet", "ptr", pimg, "int64", cvScalar, "ptr", 0, "Cdecl")

DllCall("opencv_highgui2413.dll\cvShowImage", "AStr", window, "ptr", pimg, "Cdecl")
msgbox ok
But this work:

Code: Select all

width := 100
height := 100
window := "test"

DllCall("LoadLibrary", "Str", "opencv_core2413.dll", "Ptr")
DllCall("LoadLibrary", "Str", "opencv_highgui2413.dll", "Ptr")

pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")
DllCall("opencv_core2413.dll\cvSet", "ptr", pimg, "Double", 255, "Double", 255, "Double", 255, "Double", 255, "ptr", 0, "Cdecl") 
DllCall("opencv_highgui2413.dll\cvShowImage", "AStr", window, "ptr", pimg, "Cdecl")
msgbox ok
Therefore question - Is it possible to pass copy of structure to function in autohotkey as it done in autoit?
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Passing structure to function

29 Dec 2018, 13:02

malcev wrote:
29 Dec 2018, 12:25
This code does not work:

Code: Select all

width := 100
height := 100
window := "test"

DllCall("LoadLibrary", "Str", "opencv_core2413.dll", "Ptr")
DllCall("LoadLibrary", "Str", "opencv_highgui2413.dll", "Ptr")

VarSetCapacity(cvsize, 8, 0)
NumPut(width, cvsize, 0, "int")
NumPut(height, cvsize, 4, "int")
pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")
Try

Code: Select all

MsgBox, % pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int64P", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function

29 Dec 2018, 13:18

It does not return error, but result structure is corrupted:
https://docs.opencv.org/2.4/modules/cor ... l#IplImage

Code: Select all

width := 100
height := 100

DllCall("LoadLibrary", "Str", "opencv_core2413.dll", "Ptr")

VarSetCapacity(cvsize, 8, 0)
NumPut(width, cvsize, 0, "int")
NumPut(height, cvsize, 4, "int")
pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int64P", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")
loop 22
   fin .= NumGet(pimg+0, (A_Index-1)*4, "int") "`n"
msgbox % clipboard := fin   ; wrong
fin := ""

pimg := DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 1, "Cdecl Ptr")
loop 22
   fin .= NumGet(pimg+0, (A_Index-1)*4, "int") "`n"
msgbox % clipboard := fin   ; right
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Passing structure to function

29 Dec 2018, 15:28

In c (cdecl), as far as I know, passing a struct by value is done by copying it on to the stack, including padding. Your only option to put something on the stack, is by passing parameters via dllcall. I'd expect stdcall behaves the same.
just me wrote:will most likely work only for a 32-bit DLL.
For x64 calling convention, refer to MSDN,
Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed as if they were integers of the same size. Structs or unions of other sizes are passed as a pointer to memory allocated by the caller.
So indeed, struct S {int;int;} must be passed as int64 for x64 calling convention, and it can be for cdecl too. But struct S2 {char c1;short s;char c2;} would need to be passed as "ptr", &S2 for x64. But, for cdecl, S2 would be passed as "int64", c1 | (s << 16) | (c2 << 32), you cannot do "char", c1, "short", s, "char", c2. Finally struct d {double; double; ... double;} must be passed as "ptr", &d for x64 and "double", d1, ..., "double", dn for cdecl.

@swagfag, you can do it like this,

Code: Select all

VarSetCapacity(cvsize, 14, 0)
strPut("429496729700", &cvsize)
DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
;)

Cheers :fireworks: :champagne:.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Passing structure to function

30 Dec 2018, 10:21

Helgef, may be this information and your examples will be useful here?
https://autohotkey.com/docs/commands/DllCall.htm#struct
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Passing structure to function

30 Dec 2018, 10:49

malcev wrote:
30 Dec 2018, 10:21
Helgef, may be this information and your examples will be useful here?
https://autohotkey.com/docs/commands/DllCall.htm#struct
Passing structs like this is not considered good practice and does not see common use.
Perhaps there is a better dll that you can use that does show this kind of behavior.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Passing structure to function

30 Dec 2018, 16:23

Helgef, may be this information and your examples will be useful here?
If information were to go to the documentation, more research would be needed, we cannot depend on helgef memory in the docs. And as nnnik says, it is not very common. I wouldn't ditch the dll because it passes small structs by value though.

Next year, I will write a function for this.

Happy new year all, cheers.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: OrangeCat, wilkster and 124 guests