swoop Posted May 30, 2021 Share Posted May 30, 2021 (edited) I am working on a ZeroMQ UDF and have gotten most of the AutoIt wrapper functions and constants finished. But I am encountering some difficulties with a few of the ZMQ exported functions and would kindly ask if anyone can guide me on the best way to accomplish it in AutoIt. 1) Am I creating the right struct for zmq_msg_t ? 2) Is my zmq_free_fn usage in AutoIt similar to the my_free function in the ZMQ C++ example? The usage of the exported ZMQ function zmq_msg_init_data in C++ is this: typedef void (zmq_free_fn) (void *data, void *hint); typedef struct {unsigned char _ [32];} zmq_msg_t; void ffn (void *data_, void *hint_) { // Signal that ffn has been called by writing "freed" to hint (void) data_; // Suppress 'unused' warnings at compile time memcpy (hint_, (void *) "freed", 5); } void my_free (void *data, void *hint) { free (data); } /* ... */ void *data = malloc (6); assert (data); memcpy (data, "ABCDEF", 6); zmq_msg_t msg; rc = zmq_msg_init_data (&msg, data, 6, my_free, NULL); assert (rc == 0); My AutoIt wrapper function for the DllCall is currently this: Global Const $tag_zmq_msg_t = "struct;BYTE var1" Global $tzmq_msg_t = DllStructCreate($tag_zmq_msg_t) ; this step would actually use zmq_msg_init Func zmq_msg_init_data($pMsg,$pData,$iSize,$pHint) Local $aDllCallReturn = DllCall("libzmq.dll","LONG","zmq_msg_init_data","STRUCT*",$pMsg,"PTR",$pData, "UINT",$iSize,"PTR",zmq_free_fn($pData,$pHint),"PTR",$pHint) Return $aDllCallReturn[0] EndFunc Func zmq_free_fn($pData=0,$pHint=0) $pData = 0 EndFunc Local $tzmq_msg = DllStructSetData($tzmq_msg_t, 1, "ABCDEF") Local $tzmq_data = DllStructGetPtr($tzmq_msg) Local $rc = zmq_msg_init_data($tzmq_msg,$tzmq_data,6,null) The export of the C++ function call looks like this for zmq_msq_init_data: int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint); And a description for the zmq_msg_init_data function is here: http://api.zeromq.org/master:zmq-msg-init-data Also, there is some code in the ZeroMQ library that handles different OS arch during compilation of the libzmq.dll for the struct memory alignment: typedef struct zmq_msg_t { #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) __declspec(align (8)) unsigned char _[64]; #elif defined(_MSC_VER) \ && (defined(_M_IX86) || defined(_M_ARM_ARMV7VE) || defined(_M_ARM)) __declspec(align (4)) unsigned char _[64]; #elif defined(__GNUC__) || defined(__INTEL_COMPILER) \ || (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \ || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) unsigned char _[64] __attribute__ ((aligned (sizeof (void *)))); #else unsigned char _[64]; #endif } zmq_msg_t; References:http://api.zeromq.org/master:zmq-msg-init-datahttps://travlr.github.io/libzmq/structzmq__msg__t.htmlhttps://github.com/zeromq/libzmq/blob/2ac9755ee9df54e453958136bd17fee5819dbdba/include/zmq.h#L236https://github.com/zeromq/libzmq/blob/3070a4b2461ec64129062907d915ed665d2ac126/src/msg.hpp#L46https://github.com/zeromq/libzmq/blob/3070a4b2461ec64129062907d915ed665d2ac126/src/msg.hpp#L45https://github.com/zeromq/libzmq/blob/3070a4b2461ec64129062907d915ed665d2ac126/src/zmq.cpp#L624 Edited May 30, 2021 by swoop Link to comment Share on other sites More sharing options...
TheXman Posted May 30, 2021 Share Posted May 30, 2021 (edited) Since I don't have a copy of the DLL and can't run your script, can you say what happens when you run your script? The first thing I notice is that you are using a stdcall calling convention. Although I'm not sure because I haven't dug into the headers, but I'm pretty sure you should be using cdecl (for 32bit execution). If it is 64bit, it's not necessary. Edited May 30, 2021 by TheXman CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
swoop Posted May 30, 2021 Author Share Posted May 30, 2021 40 minutes ago, TheXman said: Since I don't have a copy of the DLL and can't run your script, can you say what happens when you run your script? The first thing I notice is that you are using a stdcall calling convention. Although I'm not sure because I haven't dug into the headers, but I'm pretty sure you should be using cdecl (for 32bit execution). If it is 64bit, it's not necessary. I'm not sure if my knowledge of AutoIt DllStruct and the C++ typedef is correct. Is the following: typedef struct {unsigned char _ [32];} zmq_msg_t; equivalent to: Global Const $tag_zmq_msg_t = "struct;BYTE var1" When I run the AutoIt snippet, I get the following attached error. Error parsing function call. The DLL can be found here in the latest release from ZeroMQ: https://github.com/zeromq/libzmq/releases Link to comment Share on other sites More sharing options...
Nine Posted May 30, 2021 Share Posted May 30, 2021 (edited) The code you have posted is full of errors. You need to read the basics of AutoIt in help file. For that particular error, you cannot split statement between multiple lines without using _ at the end of a line. For the tag, it is badly formatted. And you need to add error handling so you know if the statements are successful or not. Please take a moment to read and understand the statements from help file. Edited May 30, 2021 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
TheXman Posted May 30, 2021 Share Posted May 30, 2021 (edited) 20 minutes ago, swoop said: Global Const $tag_zmq_msg_t = "struct;BYTE var1" Close, but I think it would look something like this: Const $tag_zmq_msg_t = "struct; BYTE var1[32]; endstruct;" Or just: Const $tag_zmq_msg_t = "BYTE var1[32];" since the struct/endstruct is implied in this case. Edited May 30, 2021 by TheXman swoop 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
JockoDundee Posted May 30, 2021 Share Posted May 30, 2021 14 minutes ago, Nine said: The code you have posted is full of errors. I coulda sworn you had said something about undeclared variables Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
swoop Posted May 30, 2021 Author Share Posted May 30, 2021 @Nine You're right, I didn't check the line split. My bad. You're also right about the error checking. I tried to check if the zeromq dll call is not working for a simpler function using the DllCall generator to get the ZMQ version information, and I get back: "DllCall error (libzmq.dll/zmq_version): Unable to use the DLL file. Possibly a problem with the parameters." $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","ptr","zmq_version","LONG_PTR","$major","LONG_PTR","$minor","LONG_PTR","$patch") If @error Then Switch @error Case 1 MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Unable to use the DLL file. Possibly a problem with the parameters.") Case 2 MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Unknown return type.") Case 3 MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Function not found in DLL file. Remember that function names are case sensitive.") Case 4 MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Incorrect number of parameters.") Case 5 MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Bad parameter.") Case Else MsgBox(0,"DllCall Code Generator","DllCall error (libzmq.dll/zmq_version): Unknown/unspecified error.") EndSwitch $vDllCallReturn = "" Else $vDllCallReturn = $aDllCallReturn[0] $major = $aDllCallReturn[1] $minor = $aDllCallReturn[2] $patch = $aDllCallReturn[3] MsgBox(0,"DllCall Code Generator","$major = " & $major & @CRLF & "$minor = " & $minor & @CRLF & "$patch = " & $patch & @CRLF & "DllCall return value: " & $vDllCallReturn) EndIf http://api.zeromq.org/master:zmq-version void zmq_version (int *major, int *minor, int *patch); @TheXman Thank you for the correction. Link to comment Share on other sites More sharing options...
TheXman Posted May 30, 2021 Share Posted May 30, 2021 (edited) As your link points out, the declaration of the function is: void zmq_version (int *major, int *minor, int *patch); The test script below works for me: #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> zeromq_test() Func zeromq_test() Local $aResult $aResult = DllCall("libzmq-v142-mt-4_3_4.dll", "none", "zmq_version", _ "int*", Null, _ ;Major "int*", Null, _ ;Minor "int*", Null) ;Patch If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "DllCall Error - @error = " & @error) ConsoleWrite(StringFormat("zeroMQ Version = %s.%s.%s", $aResult[1], $aResult[2], $aResult[3]) & @CRLF) EndFunc Console Output: zeroMQ Version = 4.3.4 Edited May 30, 2021 by TheXman swoop and JockoDundee 2 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
swoop Posted May 30, 2021 Author Share Posted May 30, 2021 Perfect. Thanks a bunch @TheXman for the correction, and trying it out. Very much appreciated. I will try to go through more of the functions, and make sure I compile for 64-bit when using that DLL. Link to comment Share on other sites More sharing options...
Nine Posted May 30, 2021 Share Posted May 30, 2021 1 hour ago, JockoDundee said: I coulda sworn you had said something about undeclared variables Mirage ? Excessive use of prohibited substance ? Magical mystery ? JockoDundee 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
swoop Posted May 31, 2021 Author Share Posted May 31, 2021 @TheXman I tried to get further with the ZeroMQ initialization functions. The zmq_msg_init and zmq_msg_close appear to run fine, returning 0. #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** Const $tag_zmq_msg_t = "BYTE var1[32];" Const $tag_zmq_msg_t64 = "BYTE var1[64];" Func zmq_msg_init($pMsg) ; zmq_msg_init - initialise empty ØMQ message : int zmq_msg_init (zmq_msg_t *msg); ; http://api.zeromq.org/master:zmq-msg-init Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_init","struct*",$pMsg) Return $aDllCallReturn[0] EndFunc Func zmq_msg_close($pMsg) ; zmq_msg_close - release ØMQ message : int zmq_msg_close (zmq_msg_t *msg); ; http://api.zeromq.org/master:zmq-msg-close Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_close","struct*",$pMsg) Return $aDllCallReturn[0] EndFunc ConsoleWrite(@CRLF & @CRLF & @CRLF) Global $msg = DllStructCreate($tag_zmq_msg_t) ; Test Simple Msg Init and Close ConsoleWrite(StringFormat("Init Message Result = %s", zmq_msg_init($msg)) & @CRLF) ConsoleWrite(StringFormat("Closing Message Result = %s", zmq_msg_close($msg)) & @CRLF) Although I am getting the zmq_msg_init_data to run, it sometimes does not get to the end of the script and terminate. Am I missing something simple? expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** Const $tag_zmq_msg_t = "BYTE var1[32];" Const $tag_zmq_msg_t64 = "BYTE var1[64];" Func zmq_free_fn(ByRef $pData, ByRef $pHint) $pData = 0 $pHint = 0 EndFunc Func zmq_msg_init_data($pMsg,$pData,$iSize,$hHandle,$pHint) ; zmq_msg_init_data - initialise ØMQ message from a supplied buffer ; typedef void (zmq_free_fn) (void *data, void *hint); ; int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint); ; http://api.zeromq.org/master:zmq-msg-init-data Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_init_data","struct*",$pMsg,"ptr",$pData,"uint",$iSize,"ptr",DllCallbackGetPtr($hHandle),"ptr",$pHint) Return $aDllCallReturn[0] EndFunc Func zmq_msg_close($pMsg) ; zmq_msg_close - release ØMQ message : int zmq_msg_close (zmq_msg_t *msg); ; http://api.zeromq.org/master:zmq-msg-close Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_close","struct*",$pMsg) Return $aDllCallReturn[0] EndFunc ConsoleWrite(@CRLF & @CRLF & @CRLF) Global $msg = DllStructCreate($tag_zmq_msg_t) ; Show Message Pointer/Size ConsoleWrite(StringFormat("Message Ptr = %s", DllStructGetPtr($msg)) & @CRLF) ConsoleWrite(StringFormat("Message Size = %s", DllStructGetSize($msg)) & @CRLF) ; Create and Set Data Const $tag_data = "BYTE var1[6];" Global $data = DllStructCreate($tag_data) DllStructSetData($data, 1, "ABCDEF") ; Show Data Size ConsoleWrite(StringFormat("Data Ptr = %s", DllStructGetPtr($data)) & @CRLF) ConsoleWrite(StringFormat("Data Size = %s", DllStructGetSize($data)) & @CRLF) ; Create callback function. Global $hHandle = DllCallbackRegister("zmq_free_fn", "none", "pData;pHint") ; Init message data ConsoleWrite(StringFormat("zmq_msg_init_data = %s", zmq_msg_init_data(DllStructGetPtr($msg),DllStructGetPtr($data),6,$hHandle,null)) & @CRLF) ; Msg Close ConsoleWrite(StringFormat("Closing Message = %s", zmq_msg_close($msg)) & @CRLF) ; Delete callback function. DllCallbackFree($hHandle) I'm trying to mimic the C++ example given by the documentation: http://api.zeromq.org/master:zmq-msg-init-data void my_free (void *data, void *hint) { free (data); } /* ... */ void *data = malloc (6); assert (data); memcpy (data, "ABCDEF", 6); zmq_msg_t msg; rc = zmq_msg_init_data (&msg, data, 6, my_free, NULL); assert (rc == 0); Link to comment Share on other sites More sharing options...
Nine Posted May 31, 2021 Share Posted May 31, 2021 Your DllCallbackRegister is badly formatted. The parameters must follow DllCall types. As I already told you, put some error handling... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
swoop Posted May 31, 2021 Author Share Posted May 31, 2021 Added some error messages, and there is an error code = 2 for the DllCallbackRegister shown as "ERROR: Registering ZMQ_FREE_F Error - @error = 2" Message Ptr = 0x000001D72E9D0FC0 Message Size = 32 Success: DllStructCreate($tag_data) Success: DllStructSetData($data... Data Ptr = 0x000001D72E9CB350 Data Size = 6 FuncName = ZMQ_FREE_FN ERROR: Registering ZMQ_FREE_F Error - @error = 2 zmq_msg_init_data = 0 Success: zmq_msg_init_data(... Closing Message = 0 Success: zmq_msg_close($msg) Success: DllCallbackFree($hHandle) !>07:32:56 AutoIt3.exe ended.rc:-1073740940 +>07:32:56 AutoIt3Wrapper Finished. >Exit code: 3221226356 Time: 2.114 I didn't find any error code references in the help file. If it is the same as the DllCall error code, then does that mean the "unknown error?" Here's the code: expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <constants.au3> Const $tag_zmq_msg_t = "BYTE var1[32];" Const $tag_zmq_msg_t64 = "BYTE var1[64];" ConsoleWrite(@CRLF & @CRLF & @CRLF) Global $msg = DllStructCreate($tag_zmq_msg_t) ; Show Message Pointer/Size ConsoleWrite(StringFormat("Message Ptr = %s", DllStructGetPtr($msg)) & @CRLF) ConsoleWrite(StringFormat("Message Size = %s", DllStructGetSize($msg)) & @CRLF) ; Create and Set Data Const $tag_data = "BYTE var1[6];" Global $data = DllStructCreate($tag_data) console_error (@error, "DllStructCreate($tag_data)") DllStructSetData($data, 1, "ABCDEF") console_error (@error, "DllStructSetData($data...") ; Show Data Size ConsoleWrite(StringFormat("Data Ptr = %s", DllStructGetPtr($data)) & @CRLF) ConsoleWrite(StringFormat("Data Size = %s", DllStructGetSize($data)) & @CRLF) ; Check to see what's the function's name ConsoleWrite("FuncName = " & FuncName(zmq_free_fn) & @CRLF) ; Create callback function. Global $hHandle = DllCallbackRegister("ZMQ_FREE_FN", "none", "pData;ptr;pHint;ptr") console_error (@error, "Registering ZMQ_FREE_F") ; Init message data ConsoleWrite(StringFormat("zmq_msg_init_data = %s", zmq_msg_init_data(DllStructGetPtr($msg),DllStructGetPtr($data),6,$hHandle,null)) & @CRLF) console_error (@error, "zmq_msg_init_data(...") ; Msg Close ConsoleWrite(StringFormat("Closing Message = %s", zmq_msg_close($msg)) & @CRLF) console_error (@error, "zmq_msg_close($msg)") ; Delete callback function. DllCallbackFree($hHandle) console_error (@error, "DllCallbackFree($hHandle)") ; Functions Func zmq_free_fn($pData, $pHint) ;Func zmq_free_fn(ByRef $pData, ByRef $pHint) $pData = 0 ; free $pData memory $pHint = 0 ; free $pHint memory EndFunc Func zmq_msg_init_data($pMsg,$pData,$iSize,$hHandle,$pHint) ; zmq_msg_init_data - initialise ØMQ message from a supplied buffer ; typedef void (zmq_free_fn) (void *data, void *hint); ; int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint); ; http://api.zeromq.org/master:zmq-msg-init-data Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_init_data","struct*",$pMsg,"ptr",$pData,"uint",$iSize,"ptr",DllCallbackGetPtr($hHandle),"ptr",$pHint) Return $aDllCallReturn[0] EndFunc Func zmq_msg_close($pMsg) ; zmq_msg_close - release ØMQ message : int zmq_msg_close (zmq_msg_t *msg); ; http://api.zeromq.org/master:zmq-msg-close Local $aDllCallReturn = DllCall("libzmq-v142-mt-4_3_4.dll","int","zmq_msg_close","struct*",$pMsg) Return $aDllCallReturn[0] EndFunc Func console_error ($errno, $tag) If $errno Then ConsoleWrite("ERROR: " & $tag & " Error - @error = " & $errno & @CRLF) Else ConsoleWrite("Success: " & $tag & @CRLF) EndIf EndFunc If I use the following for the zmq_free_fn function with ByRef instead: Func zmq_free_fn(ByRef $pData, ByRef $pHint) $pData = 0 ; free data from memory $pHint = 0 ; free hint from memory EndFunc Message Ptr = 0x000001B81A7CC220 Message Size = 32 Success: DllStructCreate($tag_data) Success: DllStructSetData($data... Data Ptr = 0x000001B81A7CBCC0 Data Size = 6 FuncName = ZMQ_FREE_FN ERROR: Registering ZMQ_FREE_F Error - @error = 3 !>07:31:46 AutoIt3.exe ended.rc:-1073740940 +>07:31:46 AutoIt3Wrapper Finished. >Exit code: 3221226356 Time: 2.261 I get an error 3 (I don't know, Function not found?) from the DllCallbackRegister function, and the rest of the script doesn't execute. Should the data type for the call back parameters be written as: ; Create callback function. Global $hHandle = DllCallbackRegister("zmq_free_fn", "none", "pData;ptr;pHint;ptr") or should it be: ; Create callback function. Global $hHandle = DllCallbackRegister("zmq_free_fn", "none", "pData;none;pHint;none") Link to comment Share on other sites More sharing options...
Nine Posted May 31, 2021 Share Posted May 31, 2021 Global $hHandle = DllCallbackRegister(zmq_free_fn, "none", "ptr;ptr") You can remove double quotes around any reference to functions. It will make it detectable for au3check if the function is wrong. swoop 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
swoop Posted May 31, 2021 Author Share Posted May 31, 2021 @Nine Much appreciation for the help. Can't thank you enough for the guidance. Doing that allows the zmq_msg_init_data and the callback function to register and run without error. I now need to track down why the zmq_free_fn doesn't seem to clean up or free that memory. Does "ptr;ptr" for DllCallbackRegister params mean that for AutoIt functions being called back, one doesn't need to use the parameter names of the function? Global $hHandle = DllCallbackRegister(zmq_free_fn, "none", "ptr;ptr") Again, thanks for the help as I'm still a beginner with AutoIt. Link to comment Share on other sites More sharing options...
TheXman Posted May 31, 2021 Share Posted May 31, 2021 (edited) Another issue from your last post: You define the following 2 constants. Where did you get the understanding that a zmq msg type could be 32 bytes? Your definitions: Const $tag_zmq_msg_t = "BYTE var1[32];" Const $tag_zmq_msg_t64 = "BYTE var1[64];" The header file defines zmq_msg_t as: /* Some architectures, like sparc64 and some variants of aarch64, enforce pointer * alignment and raise sigbus on violations. Make sure applications allocate * zmq_msg_t on addresses aligned on a pointer-size boundary to avoid this issue. */ typedef struct zmq_msg_t { #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) __declspec(align (8)) unsigned char _[64]; #elif defined(_MSC_VER) \ && (defined(_M_IX86) || defined(_M_ARM_ARMV7VE) || defined(_M_ARM)) __declspec(align (4)) unsigned char _[64]; #elif defined(__GNUC__) || defined(__INTEL_COMPILER) \ || (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \ || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) unsigned char _[64] __attribute__ ((aligned (sizeof (void *)))); #else unsigned char _[64]; #endif } zmq_msg_t; That says that a zmq_msg_t is 64 bytes. Since the default byte boundary for a struct created with DllStructCreate is 8, you don't need to explicitly set the alignment but it wouldn't hurt for the sake of readability and explicit translation. You don't have to because anything on an 8 byte boundary is also on a 4 byte boundary. You could do something like: Global $tag_zmq_msg_t = (@AutoItX64 ? "align 8;" : "align 4;") & "byte var[64];" ;Explicit boundaries or Global $tag_zmq_msg_t = "byte var[64];" ; Implicit 8 byte boundary In your script, you used the 32 byte definition. If an API function is expecting 64 bytes, and it only is given 32 bytes, bad things can happen. At the least, you can have unexpected results. You used: Global $msg = DllStructCreate($tag_zmq_msg_t) One more word of advice, in the functions that call the API's, after each DllCall, you should check both the @error and the API's return code (if one exists) to make sure that the API call was successful. If the API call is not successful, you should signal to the caller that the function failed. Many scripts use SetError() for this purpose. That also means that it might be better not to call those functions within other functions, like you are currently doing. By calling the functions within other functions, you don't have the ability to make sure that the function was successful. For example you do this: ConsoleWrite(StringFormat("zmq_msg_init_data = %s", zmq_msg_init_data(DllStructGetPtr($msg),DllStructGetPtr($data),6,$hHandle,null)) & @CRLF) When it might be better to do something like this: $someVar = zmq_msg_init_data(DllStructGetPtr($msg),DllStructGetPtr($data),6,$hHandle,null) If @error Then Return MsgBox($MB_ICONERROR, "ERROR", "Some error occured. @error = " & @error) ConsoleWrite("zmq_msg_init_data = " & $someVar & @CRLF) Like I said, this assumes that zmq_msg_init_data() appropriately sets @error if an error was encountered. The other benefit to using similar logic is that you don't continue when an error has occurred. Obviously if you were not successful in initializing your msg data, you shouldn't continue. Edited May 31, 2021 by TheXman Reworded last bit of advice. swoop 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 31, 2021 Moderators Share Posted May 31, 2021 TheXman, Just as an aside, thanks for the clear explanations. I learn a lot from your posts on DLLcalls and structs generally. M23 TheXman 1 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
swoop Posted May 31, 2021 Author Share Posted May 31, 2021 Quote You define the following 2 constants. Where did you get the understanding that a zmq msg type could be 32 bytes? I tried to look at how different languages have implemented ZMQ bindings, and also did a search through Github for more information at the ZMQ repository. I saw references at https://travlr.github.io/libzmq/structzmq__msg__t.html that show: typedef struct {unsigned char _ [32];} zmq_msg_t; I've seen some people use this instead for 64-bit and similarly for 32-bit: type zmq_msg_t = ubyte unsigned char 8 __(0 to 63) as ubyte They all "seem" to work for those language binding implementations. In the msg.cpp, on line 44, there is code that shows: // Check whether the sizes of public representation of the message (zmq_msg_t) // and private representation of the message (zmq::msg_t) match. typedef char zmq_msg_size_check[2 * ((sizeof (zmq::msg_t) == sizeof (zmq_msg_t)) != 0) - 1]; bool zmq::msg_t::check () const { return _u.base.type >= type_min && _u.base.type <= type_max; } Reference: https://github.com/zeromq/libzmq/blob/master/src/msg.cpp#L44 The msg.hpp, https://github.com/zeromq/libzmq/blob/2ac9755ee9df54e453958136bd17fee5819dbdba/include/zmq.h#L229 has the definition that you refer to: /******************************************************************************/ /* 0MQ message definition. */ /******************************************************************************/ /* Some architectures, like sparc64 and some variants of aarch64, enforce pointer * alignment and raise sigbus on violations. Make sure applications allocate * zmq_msg_t on addresses aligned on a pointer-size boundary to avoid this issue. */ typedef struct zmq_msg_t { #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) __declspec(align (8)) unsigned char _[64]; #elif defined(_MSC_VER) \ && (defined(_M_IX86) || defined(_M_ARM_ARMV7VE) || defined(_M_ARM)) __declspec(align (4)) unsigned char _[64]; #elif defined(__GNUC__) || defined(__INTEL_COMPILER) \ || (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \ || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) unsigned char _[64] __attribute__ ((aligned (sizeof (void *)))); #else unsigned char _[64]; #endif } zmq_msg_t; That's the definition of zmq_msg_t within the ZMQ code for the DLL. Quote In your script, you used the 32 byte definition. If an API function is expecting 64 bytes, and it only is given 32 bytes, bad things can happen. At the least, you can have unexpected results. That's what I'm experiencing running the functions. They do run and no errors generated, but there are unexpected issues. That's probably because of the memory alignment you refer to. @TheXman Thanks again for the suggestions and you're absolutely right. It really helps me muddle through learn how to implement this. Link to comment Share on other sites More sharing options...
Nine Posted May 31, 2021 Share Posted May 31, 2021 53 minutes ago, swoop said: I now need to track down why the zmq_free_fn doesn't seem to clean up or free that memory. It is because you are zeroing the pointer not the struct. 54 minutes ago, swoop said: one doesn't need to use the parameter names of the function? Exactly swoop 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
TheXman Posted May 31, 2021 Share Posted May 31, 2021 (edited) 1 hour ago, swoop said: That's the definition of zmq_msg_t within the ZMQ code for the DLL. Yes, I used the definition in the zmq.h header file, from the latest version of the ZeroMQ DLL for Windows (libzmq-v142-x64-4_3_4.zip), on the page that you referred to in the 3rd post. That's probably the one that you should rely on since you are using the DLL built from that source -- at least I hope that's what you are using. Edited May 31, 2021 by TheXman Corrected the name of the latest DLL file swoop 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman 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