Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[Class _Struct]+[Func sizeof] ! updated 01.04.12 ! ++AHKv2


  • Please log in to reply
219 replies to this topic
just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011
Working on my DllStruct class I was wondering about

Windows Data Types[*:2n08d9d6]HFILE
A handle to a file opened by OpenFile, not CreateFile.
This type is declared in WinDef.h as follows:
typedef int HFILE;

[*:2n08d9d6]HRESULT
The return codes used by COM interfaces. For more information, see Structure of the COM Error Codes. To test an HRESULT value, use the FAILED and SUCCEEDED macros.
This type is declared in WinNT.h as follows:
typedef LONG HRESULT;

Are this definitions used in 64-bit environments too?

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Yes.

just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011
... then I think this
HFILE:=A_PtrSize,HRESULT:=A_PtrSize
has to be corrected.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
New Version available, now on github as well ;)

Before I get to new features:

Thanks infogulch.

It would be nice if one could pass both the struct definition and an object/array with values to populate it with.

This is already supported ;)

If the script supports unions...

Yes it does :D
MyStruct := "
(
union {
  DWORD dw;
  struct {
    WORD lo;
    WORD hi;
  };
};
)"
struct:=new _Struct("MyStruct")
struct.dw:=4294967295 
MsgBox % struct.lo "-" struct.hi

HotKeyIt: If this is getting too off-topic, I can split the thread.

That's not a problem :)

... then I think this

HFILE:=A_PtrSize,HRESULT:=A_PtrSize
has to be corrected.

Thanks for checking this, I have corrected these and some other ;)



It is now possible to create pointer and pointer of pointer.
It is now possible to access array of pointers dynamically.

Here is an example using AutoHotkey_H.
#include <_Struct>
_AHKFuncParam := "*_AHKVar var,UShort is_byref,UShort default_type,{default_str,Int64 default_int64,Double default_double}"
_AHKFunc := "PTR vTable,LPTSTR name,{PTR BIF,*_AHKLine JumpToLine},*_AHKFuncParam Param,Int ParamCount,Int MinParams,*_AHKVar var,*_AHKVar LazyVar,Int VarCount,Int VarCountMax,Int LazyVarCount,Int Instances,*_AHKFunc NextFunc,BYTE DefaultVarType,BYTE IsBuiltIn"
_AHKVar := "{Int64 ContentsInt64,Double ContentsDouble,object},{char *mByteContents,LPTSTR CharContents},{UINT_PTR Length,_AHKVar *AliasFor},{UINT_PTR Capacity,UINT_PTR BIV},BYTE HowAllocated,BYTE Attrib,BYTE IsLocal,BYTE Type,LPTSTR Name"

a:=1 , b:=2 , c:=3
MsgBox % ShowVars(a,b,c)

ShowVars(ByRef _1="",ByRef _2="",ByRef _3="",ByRef _4="",ByRef _5="",ByRef _6="",ByRef _7="",ByRef _8="",ByRef _9="",ByRef _10=""){
   global
   param:=(new _Struct("_AHKFunc",FindFunc(A_ThisFunc))).param
   Loop 10
      if (param[A_Index].var.type=0) ;param[A_Index].var.AliasFor[""]) ;alias
         str .= "`n" param[A_Index].var.AliasFor.name "=" _%A_Index%
   Return SubStr(str, 2)
}

Here is my test file which also explains the usage (especially for pointers):
#include <_Struct>
SUCCESS(SUCCESS,TEXT){
   Return (SUCCESS?"SUCCESS":"FAIL") "`t`t" TEXT "`n"
}
MyStructure:="UInt a, Uint b" ;used below

; GENERAL USAGE
   ; DEFAULT TYPES
      ; CREATE STRUCTURE
         struct := new _Struct("INT64")
      ; SET VALUE
         NumPut(1000,struct[""],0,"INT64")
      ; GET VALUE
         RESULT .= SUCCESS(NumGet(struct[""],0,"INT64")=1000,"INT64")
   ; SIMPLE STRUCTURE USAGE
      ; CREATE STRUCTURE
         struct := new _Struct("int x,int y")
      ; SET VALUE
         struct.x := 100 , struct.y := 200
      ; GET VALUE
         RESULT .= SUCCESS(struct.x=100 && struct.y=200,"Int x,Int y")
   ; PREDEFINED STRUCTURES
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; CREATE STRUCTURE
         struct := new _Struct(MyStruct) ; can be new _Struct("MyStruct") to be able to call from non global functions
      ; SET VALUE
         struct.x := 300 , struct.y := 400
      ; GET VALUE
         RESULT .= SUCCESS(struct.x=300 && struct.y = 400,"MyStruct : int x,int y")
; POINTER USAGE
   ; DEFAULT TYPE POINTER
      ; CREATE STRUCTURE
         struct := new _Struct("INT64*")
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; SET MAIN POINTER (NOTE, HERE [] INSTEAD OF [""] MUST BE USED !!! FOR ITEMS OF STRUCTURES USE [""] ALWAYS !!!)
         struct[]:=&mem
      ; SET VALUE
         NumPut(600,struct[""],0,"INT64")
      ; GET VALUE
         RESULT .= SUCCESS(NumGet(struct[""],0,"INT64")=600 && struct[""] = &mem,"INT64*")
   ; DEFAULT TYPE POINTER USING AN ITEM IN STRUCTURE
      ; CREATE STRUCTURE
         struct := new _Struct("INT64* i")
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; SET ITEM POINTER (NOTE, HERE [""] INSTEAD OF [] MUST BE USED !!! TO SET POINTER FOR MAIN STRUCTURE USE [] !!!)
         struct.i[""]:=&mem
      ; SET VALUE
         NumPut(600,struct.i[""],0,"INT64")
      ; GET VALUE
         RESULT .= SUCCESS(NumGet(struct.i[""],0,"INT64")=600 && struct.i[""] = &mem, "INT64* i")
   ; POINTER TO USER DEFINED STRUCTURE
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; CREATE STRUCTURE
         struct := new _Struct("MyStruct*")
      ; SET POINTER (NUMPUT NEEDS TO BE USED BECAUSE THERE ARE NO ITEMS TO ACCESS THE POINTER
         NumPut(&mem,struct[""],0,"PTR")
      ; SET VALUE
         struct.x := 100 , struct.y := 200
      ; GET VALUE
         RESULT .= SUCCESS(struct.x=100 && struct.y = 200,"MyStruct*")
   ; POINTER TO USER DEFINED STRUCTURE USING AN ITEM IN STRUCTURE
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; CREATE STRUCTURE
         struct := new _Struct("MyStruct* m")
      ; SET POINTER (HERE NO NUMPUT IS REQUIRED)
         struct.m[""] := &mem
      ; SET VALUE
         struct.m.x := 300 , struct.m.y := 400
      ; GET VALUE
         RESULT .= SUCCESS(struct.m.x = 300 && struct.m.y = 400,"MyStruct* m")
; POINTER TO POINTER USAGE
   ; DEFAULT TYPE POINTER
      ; CREATE STRUCTURE
         struct := new _Struct("INT64**")
      ; SET MEMORY TO WHICH A POINTER IT WILL POINT, OUR STRUCTURE WILL POINT TO THAT POINTER
         VarSetCapacity(mem,8),NumPut(100,mem),VarSetCapacity(ptr,A_PtrSize),NumPut(&mem,ptr,0,"ptr")
      ; SET MAIN POINTER (NOTE, HERE [] INSTEAD OF [""] MUST BE USED !!! FOR ITEMS OF STRUCTURES USE [""] ALWAYS !!!)
         struct[]:=&ptr
      ; SET VALUE
         NumPut(600,NumGet(struct[""],0,"Ptr"),0,"INT64")
      ; GET VALUE
         RESULT .= SUCCESS(struct[""]=&ptr && NumGet(struct[""],0,"INT64") = &mem && NumGet(NumGet(Struct[""],0,"ptr"))=600,"INT64**")
   ; DEFAULT TYPE POINTER USING AN ITEM IN STRUCTURE
      ; CREATE STRUCTURE
         struct := new _Struct("INT64** i")
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; SET ITEM POINTER (NOTE, HERE [""] INSTEAD OF [] MUST BE USED !!! TO SET POINTER FOR MAIN STRUCTURE USE [] !!!)
         struct.i[""]:=&mem
      ; SET VALUE
         NumPut(600,struct.i[""],0,"INT64")
      ; GET VALUE
         RESULT .= SUCCESS(NumGet(struct.i[""],0,"INT64")=600 && struct.i[""] = &mem,"INT64** i")
   ; POINTER TO USER DEFINED STRUCTURE
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; CREATE STRUCTURE
         struct := new _Struct("MyStruct*")
      ; SET POINTER (NUMPUT NEEDS TO BE USED BECAUSE THERE ARE NO ITEMS TO ACCESS THE POINTER
         ;~ NumPut(&mem,struct[""],0,"PTR")
         struct[] := &ptr ;mem
      ; SET VALUE
         struct.x := 100 , struct.y := 200
      ; GET VALUE
         RESULT .= SUCCESS(struct.x=100 && struct.y=200,"MyStruct**")
   ; POINTER TO USER DEFINED STRUCTURE USING AN ITEM IN STRUCTURE
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; SET MEMORY TO WHICH IT WILL POINT
         VarSetCapacity(mem,8)
      ; CREATE STRUCTURE
         struct := new _Struct("MyStruct* m")
      ; SET POINTER (HERE NO NUMPUT IS REQUIRED)
         struct.m[""] := &mem
      ; SET VALUE
         struct.m.x := 300 , struct.m.y := 400
      ; GET VALUE
         RESULT .= SUCCESS(struct.m.x=300 && struct.m.y=400,"MyStruct* m")
; SIMPLE UINT STRUCTURE
   ; CREATE STRUCTURE
      S:=new _Struct("Uint i")
   ; SET VALUE
      S.i:=1
   ; GET VALUE
      RESULT .= SUCCESS(s.i=1 && s.i[""]=s[""], "Uint i")
   ; SET POINTER (not available)
; POINTER TO CUSTOM STRUCTURE
   ; CREATE STRUCTURE
      MyStruct:="TCHAR i",S:=new _struct("MyStruct *v")
   ; SET AND FILL MEMORY
      VarSetCapacity(mem,sizeof(MyStruct)*2),StrPut("AB",&mem)
   ; SET POINTER
      s.v[""]:=&mem
   ; SET VALUE
      s.v.2.i:="C"
   ; GET VALUE
      RESULT .= SUCCESS(s.v.1.i="A" && s.v.2.i="C" && s.v[""]=&mem, "MyStruct *v")
; ANOTHER CUSTOM STRUCTURE
   ; CREATE STRUCTURE
      Structure:="UInt a,UInt b",s:=new _Struct("Structure * s")
   ; SET AND FILL MEMORY
      VarSetCapacity(v,16),NumPut(1,v),NumPut(2,v,4),NumPut(3,v,8),NumPut(4,v,12)
   ; SET POINTER
      s.s[""]:=&v
   ; GET VALUE
      RESULT .= SUCCESS(s.s.a=1 && s.s.2.b=4 && s.s[""]=&v, "Structure * s")
   ; SET VALUE
      s.s.1.a:=10,s.s.b:=20,s.s.2.a:=30,s.s.2.b:=40
   ; GET VALUE
      RESULT .= SUCCESS(s.s.a=10 && s.s.1.b=20 && s.s.2.a=30 && s.s.2.b=40, "Structure * s")
MsgBox % Result

Enjoy coding ;)

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

; PREDEFINED STRUCTURES
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; CREATE STRUCTURE
         struct := new _Struct(MyStruct)

IMO, it would be better to create a struct definition object, then reuse all of its properties (other than the pointer to data). i.e.
_POINT := new _StructDef("int x, int y")
pt1 := new _POINT
pt2 := new _POINT


infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
I like that idea. For the library I'm making I would like to support syntax similar to:

stru := new OpenGL.Struct("GPU_DEVICE")
stru.cb := 123
stru.DeviceName := "mydevice"

Where I define the struct and call new _Struct() internally:
class OpenGL 
    ; lots of stuff here...
    
    class Struct {
        __new( struct_name ) {
            global OpenGL, _Struct
            if ObjHasKey(OpenGL.Struct, struct_name)
                return new _Struct(OpenGL.Struct[struct_name])
        }
        
        static GPU_DEVICE := "DWORD cb; CHAR DeviceName[32]; CHAR DeviceString[128]; DWORD Flags; RECT rcVirtualScreen;"
    }
}


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

stru := new OpenGL.Struct("GPU_DEVICE")

If OpenGL.GPU_DEVICE is a struct definition object in the first place, new OpenGL.GPU_DEVICE would probably look more natural (and be more efficient).

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

; PREDEFINED STRUCTURES
      ; DEFINE STRUCTURE
         MyStruct:="int x,int y"
      ; CREATE STRUCTURE
         struct := new _Struct(MyStruct)

IMO, it would be better to create a struct definition object, then reuse all of its properties (other than the pointer to data). i.e.
_POINT := new _StructDef("int x, int y")
pt1 := new _POINT
pt2 := new _POINT

I like that, so this is now possible for any structure object :)
Parameters can be passed either way round.
#include <_Struct>
_POINT := new _Struct("int x, int y")

pt1 := new _POINT
pt2 := new _POINT({x:20,y:40})
VarSetCapacity(mem,8)
pt3 := new _POINT({x:1,y:2},&mem)
pt1.x:=40
pt2.y:=30
pt3.x:=10
MsgBox % pt1.x "-" pt1.y "`n" pt2.x "-" pt2.y "`n" pt3.x "-" pt3.y "=" NumGet(mem)

Lexikos, could we allow global definitions in class, currently we get "Expected assignment or class/method definition."?
Then your suggestion could be implemented much simpler.
Class OpenGL {
	global _Struct
	static GPU_DEVICE := new _Struct("DWORD cb; CHAR DeviceName[32]; CHAR DeviceString[128]; DWORD Flags; RECT rcVirtualScreen;"
}
struct := new OpenGL.GPU_DEVICE


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Lexikos, could we allow global definitions in class, currently we get "Expected assignment or class/method definition."

Just remove the unnecessary declaration ...

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Cool :D, I did not notice this works, thank you :oops:

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Btw. when I compile _Struct using latest compiler, I get an error message:
Error at line 34 in #include file "\...\Lib\_Struct.ahk".



Line Text: static PTR:=A_PtrSize,UPTR:=A_PtrSize,SHORT:=2,USHORT:=2,INT:=4,UINT:=4,__int64:=8,INT64:=8,UINT64:=...

[color=red]Error: Expected class, var or method definition.[/color]



The program will exit.
Compiled script still works fine. Can you have a look what might be causing this error?

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
I don't get that error, but sizeof.ahk seems to get included both at the beginning and at the end of the script. Btw, were you talking to me? I didn't write the compiler. ;)

(Edit: There's an open issue for the problem I got; I forgot there was something I was supposed to change in AutoHotkey.exe to fix it.)

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
That is really weired, I have copied my lib folder and compiler folder to another location and then it works :?
I will try to find out what is going on, must be something wrong on my laptop :(

EDIT:
Shame on me, it was a wrong AutoHotkey.exe that launches /iLib :oops:

infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
How would I reference one struct from another?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Have you read trough examples above?
#include <_Struct>

MyStruct:="UInt a, Uint b"

struct:=new _Struct("MyStruct *ms,UInt a")

struct.a:=100

VarSetCapacity(s,8),struct.ms[""]:=&s ; memory for structure

struct.ms.a:=200

struct.ms.b:=300

MSgBox % struct.a "-" struct.ms.a "-" struct.ms.b





; Autohotkey_H

_AHKLine := "BYTE ActionType,BYTE Argc,WORD FileIndex,UINT LineNumber,*_AHKArgStruct Arg,PTR *Attribute,*_AHKLine PrevLine,*_AHKLine NextLine,*_AHKLine RelatedLine,*_AHKLine ParentLine"



FirstLine:=new _Struct("_AHKLINE",DllCall(A_AhkPath "\ahkExecuteLine","Uint",0,"Uint",0))

MSgBox % FirstLine.ActionType "-" FirstLine.NextLine.LineNumber "-" FirstLine.NextLine.NextLine.FileIndex