Andreik Posted March 31, 2012 Share Posted March 31, 2012 I have a struct like this one: typedef struct { char *Name; int X; int Y; } MyStruct; an array like this one: MyStruct MyArray[] = { {"Item1", 50, 24}, {"Item2", 60, 22} }; and a function: extern "C" __declspec(dllexport) int MyFunc(int *NumOfItems, MyStruct **pArray) { *NumOfItems = sizeof(MyArray)/sizeof(MyStruct); *pArray = MyArray; return 1; } My question is how should I create the properly structure in AutoIt to can call MyFunc. I'm very confuse if I should use something like Global Const $tagMyStruct = "ptr;int;int;" Global $MyStruct, $Struct $NumOfItems = DllStructCreate("int") $StructPtr = DllStructCreate("ptr") DllCall("Test.dll","int:cdecl","MyFunc","int",DllStructGetPtr($NumOfItems),"ptr",DllStructGetPtr($StructPtr)) For $Index = 1 To DllStructGetData($NumOfItems,1) $Struct &= $tagMyStruct Next $MyStruct = DllStructCreate($Struct,DllStructGetData($StructPtr,1)) $Name1 = DllStructCreate("char[64]",DllStructGetData($MyStruct,1)) ;char[64] - big enough to get the name $Name2 = DllStructCreate("char[64]",DllStructGetData($MyStruct,4)) ;char[64] - big enough to get the name MsgBox(0,"Items",DllStructGetData($Name1,1) & @CRLF & DllStructGetData($Name2,1)) or instead of ptr in $tagMyStruct can I use something some kind of char[]? When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Shaggi Posted March 31, 2012 Share Posted March 31, 2012 You can't use char arrays directly, as described in this example. This would be how i would do it, so you have a managed array instead of a large struct: Global Const $tagMyStruct = "ptr;int;int;" Global Const $sizeOfMyStruct = DllStructGetSize(DllStructCreate($tagMyStruct)) Global Const $tagCharArr = "char[64]" $Result = DllCall("Test.dll","int:cdecl","MyFunc","int*",0,"int*",0) ;breaks on x64 beware ; Result [1] should contain NumOfItems, and Result[2] should contain pointer to first MyStruct. ; Now we make an array of them. If @Error then Exit -1 Global $pArray[$Result[1] + 1] ;Array is 1-based with first index as size For $i = 1 to $Result[1] $pArray[$i] = DllStructCreate($tagMyStruct,$Result[2] + (($i - 1) * $sizeOfMyStruct)) ;Similar to pArray[i] = (MyStruct*) result[2] + i * sizeof(Mystruct) Next $pArray[0] = $result[1] ;And know you can do: For $i = 1 to $pArray[0] ConsoleWrite("x = " & DllStructGetData($pArray[$i],2) & ", y = " & DllStructGetData($pArray[$i],3) & @CRLF) ;Since autoit doesn't support char arrays like that, we have to create a temporary struct to extract: ConsoleWrite(@Tab & "name = " DllStructGetData(DllStructCreate($tagCharArr,DllStructGetData($pArray[$i],1))) & @LF) Next Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG Link to comment Share on other sites More sharing options...
Skitty Posted July 12, 2012 Share Posted July 12, 2012 (edited) I have a question, working with a little project in autoit (Specifically the scite editor clone) gave me some insight into how to make gui applications in C++, suddenly I found myself understanding (a little) some basics but now I'm having trouble with datatypes.when compiling this code, I get an "Invalid conversion from Char* to BOOL". Well, by what I can tell is that the message is correct of course and I don't know how to have this function return the data string "as is".BOOL DoFileOpen(HWND hwnd) { OPENFILENAME ofn; char szFileName[MAX_PATH]; ZeroMemory(&ofn, sizeof(ofn)); szFileName[0] = 0; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; ofn.lpstrFilter = "Text Files (*.txt)0*.txt0All Files (*.*)0*.*00"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { MessageBox(hwnd, szFileName, "Name", MB_OK | MB_ICONEXCLAMATION); return szFileName;//<-- Problem right here } return 0; }What am I missing? Edited July 12, 2012 by ApudAngelorum Link to comment Share on other sites More sharing options...
Skitty Posted July 12, 2012 Share Posted July 12, 2012 (edited) Oh, whoops.I guess I just found out that you declare the return type in the function name...CHAR* DoFileOpen() { OPENFILENAME ofn; char szFileName[MAX_PATH];//<-- warning: address of local variable 'szFileName' returned ZeroMemory(&ofn, sizeof(ofn)); szFileName[0] = 0; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; ofn.lpstrFilter = "Text Files (*.exe)0*.exe0All Files (*.*)0*.*00"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { return szFileName; } return 0; }But now I'm getting undefined reference to `GetOpenFileNameA@4'Although, it is working in one project with a simple GUI, but not in another...Edit: Damn it, I just looked into the compiler options and noticed the other project was a Console app, changing it to GUI application stopped giving me these errors.But I am getting a warning - warning: address of local variable 'szFileName' returnedWhat am I doing wrong now? Edited July 12, 2012 by ApudAngelorum Link to comment Share on other sites More sharing options...
ProgAndy Posted July 12, 2012 Share Posted July 12, 2012 (edited) If you want to return a string you have to globally allocate the required memory and free it if you have finished using it, e.g. use malloc / free: char *szFileName = (char*) malloc(MAX_PATH+1); ... free(szReturnedPath); Edited July 12, 2012 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Skitty Posted July 12, 2012 Share Posted July 12, 2012 If you want to return a string you have to globally allocate the required memory and free it if you have finished using it, e.g. use malloc / free: char *szFileName = (char*) malloc(MAX_PATH+1); ... free(szReturnedPath); I see now, thanks. I stopped getting the error but now I'm left wondering about some stuff I was reading where an article mentioned that the function "malloc" was a C function and that in C++ you would use the "new" keyword. http://www.codeproject.com/Articles/14746/Multithreading-Tutorial Second paragraph down. In the C language, you use malloc to acquire memory from the heap, and in C++, you use the new keyword. Link to comment Share on other sites More sharing options...
trancexx Posted July 12, 2012 Share Posted July 12, 2012 If you really want to return pointer to allocated memory then you would use neither new or malloc. When that is the case you have to be precise what method should be used to free memory, i.e. you have to be precise about how that memory is allocated.Operator new does not dictate the way memory is allocated. That is implementation detail for/of specific compiler.There are better ways of doing all this, for example asking for pointer to allocated memory by the caller. JScript 1 ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Valik Posted July 12, 2012 Share Posted July 12, 2012 Or using a string object so you don't have to worry about memory management at all. Also, ProgAndy, you say "globally allocate" but that's not true and means something entirely different (and bad) than what's need. All that's necessary in this case is to ensure the object lifetime is correct, it doesn't need to be global for that. Link to comment Share on other sites More sharing options...
ProgAndy Posted July 12, 2012 Share Posted July 12, 2012 You are both right. I just went for a quick and dirty solution in C and did not read the post completely. A buffer supplied per parameter (plain C), or string objects (when using C++) are the better choice. twitchyliquid64 1 *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
Skitty Posted July 12, 2012 Share Posted July 12, 2012 (edited) asking for pointer to allocated memory by the caller. I think I have an idea of what you mean? char* DoFileOpen(char path[]) { OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; ofn.lpstrFilter = "Executable (*.exe)0*.exe0All Files (*.*)0*.*00"; ofn.lpstrFile = path; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = "exe"; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { MessageBox(0, path, "Name", MB_OK | MB_ICONEXCLAMATION); return path; } return 0; } Like this? It doesn't give me an error an it seems to work. I just pass it as a parameter after its creation in the calling function right? char szFileName[MAX_PATH]; is created in the calling function instead. But one thing I'm not understanding is why the File open dialog will not come up if I comment out this line~ szFileName[0] = 0; After declaring the variable, by what I know in autoit, something like this would usually assign 0 to the first index of the array but obviously something else is happening there.... Edited July 12, 2012 by ApudAngelorum Link to comment Share on other sites More sharing options...
Valik Posted July 12, 2012 Share Posted July 12, 2012 You should not be using the Windows API yet. You still know far too little about what you are attempting to do. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now