Jump to content

How to create an array of struct ?


jlf
 Share

Recommended Posts

Hi,

I need to send an array of structure to a C function (compiled as DLL). All is ok if I try to send only this struct (DllStructCreate + DllStructSetData).

At this time, my AutoIt code use a 2Darray (see 'test.au3' and $AliasList). I need to share this 2D array (in fact an array of struct, see 'global.h') between AutoIt and DLL. Each of them should be able to modify this array of struct.

I have done an small function (see 'MyFunction.c') that works fine but only with the first element of this array of struct.

__declspec(dllexport) int MyFunction(char *Channel,struct Alias AliasList[],int AliasListLength) {
fprintf(stdout,"Channel = %s\n",Channel );
fprintf(stdout,"AliasListLength = %d\n",AliasListLength );
fprintf(stdout,"AliasList[0].ScenarioName = %s\n",AliasList[0].ScenarioName);
fprintf(stdout,"AliasList[1].ScenarioName = %s\n",AliasList[1].ScenarioName);
fprintf(stdout,"AliasList[2].ScenarioName = %s\n",AliasList[2].ScenarioName);
fprintf(stdout,"AliasList[3].ScenarioName = %s\n",AliasList[3].ScenarioName);
fprintf(stdout,"AliasList[4].ScenarioName = %s\n",AliasList[4].ScenarioName);
fflush(NULL);
return(0);
}

I create the structure, assign an item to something, and call the dll.

1st test :

Local $struct = DllStructCreate("...")
DllStructSetData($struct,2,"this is my question")
DllCall("./MyCustomDll_x64.dll","int:cdecl","MyFunction","str","file12345678","struct*",DllStructGetPtr($struct),"int",$NB_ITEM)

==> only 'AliasList[0]' is providen, and 'AliasList[0].ScenarioName' return correct value --> all is ok (and dll can update this value, perfect !)

2nd test (3rd in providen 'test.au3')

DllCall("./MyCustomDll_x64.dll","int:cdecl","MyFunction","str","file12345678","ptr*",$AliasList,"int",$NB_ITEM)

I try to send whole 2D array, and what ? Nothing good...

Does someone could help me please ? Maybe it's a wrong call, or an wrong C declaration, or both, or something else, but I cannot found what...

I think also my 2D array in AutoIt should be rewritten to match the array of struc in C-style.

Makefile providen (just rename txt to bat)

Dll (x86 & x64) compiled providen in ZIP file if you don't want to compile it.

Thanks in advance

Best Regards

test.au3

MyFunction.c

_makefile_DLL_MinGW.txt

global.h

MyCustomDll.zip

Link to comment
Share on other sites

Hi,

Posting this new post, maybe more simple : how to create an array of struct ? Like in C "struct struct_type MyStruct[ ]"

See more details in my previous post above

Thanks in advance

Edited by Melba23
Removed link as topics merged
Link to comment
Share on other sites

Something like this here?:

$tStruct = DllStructCreate("uint array[10]")
For $i = 1 To 10
    DllStructSetData($tStruct, "array", $i^2, $i)
Next

For $i = 1 To 10
    ConsoleWrite(DllStructGetData($tStruct, "array", $i) & @LF)
Next

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Autoit doesn't allow arrays of user defined types inside other structs. One way to it is by allocating a raw block of memory sized to your array, and alias your way into it, kind of like this:

$tagMYSTRUCT = "int code; char msg[10];"

$mystruct = ArrayStruct($tagMYSTRUCT, 4)
$fourth_element = getElement($mystruct, 3, $tagMYSTRUCT) ; $fourth_element is an alias of '$mystruct[3]'
DllStructSetData($fourth_element, "code", 3);

DllCall(...., "struct*", $mystruct)


Func ArrayStruct($tagStruct, $numElements)
    $sizeOfMyStruct = DllStructGetSize(DllStructCreate($tagMYSTRUCT)) // assumes end padding is included
    $numElements = 4
    $bytesNeeded = $numElements * $sizeOfMyStruct
    return DllStructCreate("byte[" & $bytesNeeded & "]")
EndFunc


Func GetElement($Struct, $Element, $tagSTRUCT)
   return DllStructCreate($tagSTRUCT, DllStructGetPointer($Struct) + $Element * DllStructGetSize(DllStructCreate($tagStruct)))
EndFunc

Its the C equivalent of doing this:

typedef struct
{
    int code;
    char msg[10];
} MyStruct;


void example() {
    MyStruct structs[10];
    something(structs);

    //or

    MyStruct * ptrstructs = (MyStruct*) malloc(sizeof MyStruct * 10);
    something(ptrstructs);
}

void something(MyStruct input[]) {}
Edited by Shaggi

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Link to comment
Share on other sites

  • Moderators

jlf,

How about sticking to the one topic at a time - merged. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I did it with arrays in arrays.

Assign struct array

$struct= structname_make()
$subarray= $struct[3]
;work on array
$subarray[0][0]+= 100
;put it back
$struct[3]= $subarray
structname_showcell($struct, 0, 0)

func structname_make()
    local $struct[4]
    $struct[0]= 0;page
    $struct[1]= 1;pages
    $struct[2]= 0;curtile
    local $rect[200][4];sub array
    $struct[3]= $rect;rects on page
    return $struct
EndFunc;structname()

func structname_showcell($struct, $index, $data)
    $subarray= $struct[3]
    consolewrite($subarray[$index][$data])
EndFunc;

I'm working on a descent example.

To make an array of struct is also pretty easy from here.

EDIT: I didn't know we were talking about DLL.

Shaggi and UEZ's example are helping me learn about DllStruct.

Edited by Xandy
Link to comment
Share on other sites

Glad it worked out :)

I did it with arrays in arrays.

Assign struct array

$struct= structname_make()
$subarray= $struct[3]
;work on array
$subarray[0][0]+= 100
;put it back
$struct[3]= $subarray
structname_showcell($struct, 0, 0)

func structname_make()
local $struct[4]
$struct[0]= 0;page
$struct[1]= 1;pages
$struct[2]= 0;curtile
local $rect[200][4];sub array
$struct[3]= $rect;rects on page
return $struct
EndFunc;structname()

func structname_showcell($struct, $index, $data)
$subarray= $struct[3]
consolewrite($subarray[$index][$data])
EndFunc;
I have been messing with code like that but it just sucks you cant reference the subarray directly (only through byref func calls, and this has an obvious problem with multiple nesting) :(

Also glad the example helped you but keep in mind it's not exactly how you're supposed to use the unmanaged autoit system (eg. avoiding the type system and does no bounds checking what so ever)..

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Link to comment
Share on other sites

Yeah, I really didn't know how I was going to do it.

It seemed AutoItObject wouldn't work with array properties or byref parameters.

I wanted 2 tilewindows a list of tiles of variable size and a list of chosen tiles to replace.

With functions to setup and calculate area of rects drawn.

Now I can work with collections instead of bunch of individual arrays.

Posted Image

I don't know anything about Dll, so every little can get me more comfortable.

Link to comment
Share on other sites

Am I missing something: see trancexx's comment.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Thanks.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

  • 1 month later...

Thanks Shaggi.

Here the other example using Array Struct.

; Drawing a Shaded Rectangle
; http://msdn.microsoft.com/en-us/library/windows/desktop/dd162485(v=vs.85).aspx

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$tagTRIVERTEX = 'LONG x;LONG y;USHORT Red;USHORT Green;USHORT Blue;USHORT Alpha'
$tagGRADIENT_RECT = 'ULONG UpperLeft;ULONG LowerRight'

$hWnd = GUICreate("Form1", 483, 339, 192, 124)
$hDC = _WinAPI_GetDC($hWnd)

GUISetState(@SW_SHOW)

$tGRADIENT_RECT = DllStructCreate($tagGRADIENT_RECT)

$taTRIVERTEX = ArrayStruct($tagTRIVERTEX, 2)

$tTRIVERTEX0 = getElement($taTRIVERTEX, 0, $tagTRIVERTEX)
$tTRIVERTEX1 = getElement($taTRIVERTEX, 1, $tagTRIVERTEX)

DllStructSetData($tTRIVERTEX0, 'x', 0)
DllStructSetData($tTRIVERTEX0, 'y', 0)
DllStructSetData($tTRIVERTEX0, 'Red', 0x0000)
DllStructSetData($tTRIVERTEX0, 'Green', 0x8000)
DllStructSetData($tTRIVERTEX0, 'Blue', 0x8000)
DllStructSetData($tTRIVERTEX0, 'Alpha', 0x0000)

DllStructSetData($tTRIVERTEX1, 'x', 300)
DllStructSetData($tTRIVERTEX1, 'y', 80)
DllStructSetData($tTRIVERTEX1, 'Red', 0x0000)
DllStructSetData($tTRIVERTEX1, 'Green', 0xD000)
DllStructSetData($tTRIVERTEX1, 'Blue', 0xD000)
DllStructSetData($tTRIVERTEX1, 'Alpha', 0x0000)

DllStructSetData($tGRADIENT_RECT, 'UpperLeft', 0)
DllStructSetData($tGRADIENT_RECT, 'LowerRight', 1)

DllCall('msimg32.dll', 'bool', 'GradientFill', 'hwnd', $hDC, 'ptr', DllStructGetPtr($taTRIVERTEX), 'ulong', 2, 'ptr', DllStructGetPtr($tGRADIENT_RECT), 'ulong', 1, 'ulong', 0)
; Equivalent
; DllCall('gdi32.dll', 'bool', 'GdiGradientFill', 'hwnd', $hDC, 'ptr', DllStructGetPtr($taTRIVERTEX), 'ulong', 2, 'ptr', DllStructGetPtr($tGRADIENT_RECT), 'ulong', 1, 'ulong', 0)

_WinAPI_ReleaseDC($hWnd, $hDC)

While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd

Func ArrayStruct($tagStruct, $numElements)
$sizeOfMyStruct = DllStructGetSize(DllStructCreate($tagStruct)) ; assumes end padding is included
$numElements = 4
$bytesNeeded = $numElements * $sizeOfMyStruct
return DllStructCreate("byte[" & $bytesNeeded & "]")
EndFunc

Func GetElement($Struct, $Element, $tagSTRUCT)
return DllStructCreate($tagSTRUCT, DllStructGetPtr($Struct) + $Element * DllStructGetSize(DllStructCreate($tagStruct)))
EndFunc
Edited by prazetto

# Button. Progressbar - Graphical AutoIt3 Control (UDF) # GTK on AutoIt3 - GTK+ Framework | Widgets

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...