TheXman Posted May 31, 2021 Share Posted May 31, 2021 (edited) 2 hours ago, swoop said: Again, thanks for the help as I'm still a beginner with AutoIt. I can see that you've been doing a lot of searching for and reading topics on how to do API calls and define structures in AutoIt. I'm sure that you've come across several good ones. In addition to those topics, there's a wealth of examples in the WinApi* UDF libs that come with AutoIt as well as many UDF libs submitted by users. If you would like a suggestion for a relatively well-formatted, well-written, and well-documented UDF lib with numerous DllCalls/Structs/Constants/Enums, may I suggest my CryptoNG UDF lib (CryptoNG.au3)? Of course I'm biased as to its quality but I also suggest it because I wrote it. So I know how it works and why any particular piece of code was written the way it was. Therefore, I can easily answer any questions that you may have about it. Not only will it give you many DllCall and DllStruct* examples, but it also has examples of how error checking can be done as well as other general formatting and coding techniques. Hopefully, it can help you quickly flatten your overall AutoIt leaning curve. If after looking through the UDF you have general AutoIt-related questions, then I would suggest you create a new topic for those questions. If you have CryptoNG-specific questions in which you think the answers may benefit other users of CryptoNG, then I suggest you post them in the CryptoNG topic. Of course if you have ZeroMQ-related questions, then continue posting them here. That way, you keep this or other topics on-point and uncluttered. Edited May 31, 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...
swoop Posted May 31, 2021 Author Share Posted May 31, 2021 3 minutes ago, TheXman said: I can see that you've been doing a lot of searching for and reading topics on how to do API calls and define structures in AutoIt. I'm sure that you've come across several good ones. In addition to those topics, there's a wealth of examples in the WinApi* UDF libs that come with AutoIt as well as many UDF libs submitted by users. If you would like a suggestion for a relatively well-formatted, well-written, and well-documented UDF lib with numerous DllCalls/Structs/Constants/Enums, may I suggest my CryptoNG UDF lib? Of course I'm biased as to its quality but I also suggest it because I wrote it. So I know how it works and why any particular piece of code was written the way it was. Therefore, I can easily answer any questions that you may have about it. Not only will it give you many DllCall and DllStruct* examples, but it also has examples of how error checking can be done as well as other general formatting and coding techniques. Hopefully, it can help you quickly flatten your overall AutoIt leaning curve. Excellent! Thanks @TheXman for the great suggestion. I will take some time out now to study your CyrptoNG UDF code to learn about how to work with the structs and DllCall. Seeing examples like this does help a lot. This is just what I needed. TheXman 1 Link to comment Share on other sites More sharing options...
swoop Posted June 1, 2021 Author Share Posted June 1, 2021 (edited) @TheXman I have been studying the CryptoNG UDF and the HttpApi UDF. Thanks again for the suggestion and help. I want to clarify if I understand how DllStructs are used in AutoIt for working with external DLLs. In the help file about DllStructCreate: https://www.autoitscript.com/autoit3/docs/functions/DllStructCreate.htm the description reads as follows: DllStructCreateCreates a C/C++ style structure to be used in DllCall. DllStructCreate ( Struct [, Pointer] ) Parameters Struct A string representing the structure to create (See Remarks). Pointer [optional] If supplied the struct will not allocate memory but use the pointer supplied. Return Value Success: a variable for use with DllStruct calls. Failure: sets the @error flag to non-zero. @error: 1 = Variable passed to DllStructCreate was not a string. 2 = There is an unknown Data Type in the string passed. 3 = Failed to allocate the memory needed for the struct, or Pointer = 0. 4 = Error allocating memory for the passed string. When we have an existing struct created by another DLL, we don't need to create that struct again in memory. But it is important to use the DllStructCreate with the optional pointer parameter in order to work with this "external" struct in AutoIt. The variable returned from DllStructCreate is used by DllStruct and other DllCall related functions to deal with an unknown pre-existing struct. Such functions as: DllCall, DllStructGetData, DllStructGetPtr, DllStructGetSize, DllStructSetData, IsDllStruct. I refer to specific DllStructCreate examples in your UDF's for my current understanding: From the HTTPAPI.au3: Func _HTTPAPI_HttpSendHttpResponse($hRequestQueue, $iRequestId, $iStatusCode, $sReason, $sBody) _DebugOut(@CRLF & "Function: HttpSendHttpResponse") Local $aResult[0] Local $pKnownHeader = Null Local $iFlags = 0 Local $tResponse = DllStructCreate($__HTTPAPI_gtagHTTP_RESPONSE_V2), _ $tCachePolicy = DllStructCreate($__HTTPAPI_gtagHTTP_CACHE_POLICY), _ $tLoggedData = DllStructCreate($__HTTPAPI_gtagHTTP_LOG_FIELDS_DATA), _ $tDataChunk = DllStructCreate($__HTTPAPI_gtagHTTP_DATA_CHUNK_FROM_MEMORY), _ $tReason = __HTTPAPI_CreateStringBuffer($sReason), _ $tBody = __HTTPAPI_CreateStringBuffer($sBody), _ $tContentType = __HTTPAPI_CreateStringBuffer("text/html"), _ $tContentLength = __HTTPAPI_CreateStringBuffer(String(DllStructGetSize($tBody))), _ $tHeader = "" ;Init response $tResponse.MajorVersion = 1 $tResponse.MinorVersion = 1 $tResponse.StatusCode = $iStatusCode $tResponse.pReason = DllStructGetPtr($tReason) $tResponse.ReasonLength = DllStructGetSize($tReason) $tResponse.LogDataType = $__HTTPAPI_HttpLogDataTypeFields ;Add known header(s) to response $pKnownHeader = DllStructGetPtr($tResponse, "KnownHeaders") + ($__HTPPAPI_HttpHeaderContentType * $__HTTPAPI_HTTP_KNOWN_HEADER_SIZE) $tHeader = DllStructCreate($__HTTPAPI_gtagHTTP_KNOWN_HEADER, $pKnownHeader) $tHeader.pRawValue = DllStructGetPtr($tContentType) $tHeader.RawValueLength = DllStructGetSize($tContentType) The specific line 1240: $tHeader = DllStructCreate($__HTTPAPI_gtagHTTP_KNOWN_HEADER, $pKnownHeader) I think that means the $tHeader struct is not created nor allocated in memory. We're just creating a struct variable to work with the struct. $pKnownHeader is a pointer to a pre-existing struct (in memory). We are creating $tHeader DLLStruct variable that contains information about the existing struct, which we know has the structure defined by $__HTTPAPI_gtagHTTP_KNOWN_HEADER. This $tHeader variable allows for us to use DllStruct functions to call and manipulate data in the memory location referred by $pKnownHeader. To apply the same idea to my ZeroMQ Dll struct code, if the ZeroMQ DLL functions create existing message structs and gives me back pointers, then I can use the DllStructCreate to do the same as you've done above. To make the message structs available for use in AutoIt via DllStrut and DllCall functions. That's also what's happening in the CryptoNG when DllStructCreate is used in the __CryptoNG_BCryptDecrypt function. From the CryptoNG.au3: expandcollapse popupFunc __CryptoNG_BCryptDecrypt($sAlgorithmId, $xData, $hEncryptionKey, $bResultIsText = True) Local $tInputBuffer = "", _ $tOutputBuffer = "", _ $tIVBuffer = "", _ $tByteBuffer = "", _ $tUlong = "" Local $iBlockLength = 0, _ $iStatusCode = 0, _ $iError = 0, _ $iOutputLength = 0 Local $aResult[0] Local $vDecryptedData = "" Local $xIV = Binary("") _DebugOut(@CRLF & "Function: __CryptoNG_BCryptDecrypt()") _DebugOut("$sAlgorithmId = " & $sAlgorithmId) _DebugOut("$xData = " & $xData) ;Get length of key $tByteBuffer = __CryptoNG_BCryptGetProperty($hEncryptionKey, $CNG_BCRYPT_KEY_LENGTH) If @error Then Return SetError(1, 0, "") $tUlong = _WinAPI_CopyStruct($tByteBuffer, "ulong value") ;If this is a block cipher (not a stream cipher) If $sAlgorithmId <> $CNG_BCRYPT_RC4_ALGORITHM Then ;Get length of block $tByteBuffer = __CryptoNG_BCryptGetProperty($hEncryptionKey, $CNG_BCRYPT_BLOCK_LENGTH) If @error Then Return SetError(1, 0, "") $tUlong = _WinAPI_CopyStruct($tByteBuffer, "ulong value") $iBlockLength = $tUlong.value _DebugOut("$iBlockLength = " & $iBlockLength) ;Create initialization vector (IV) buffer and set its default value (0x000102...) $xIV = Binary("") For $i = 0 To $iBlockLength - 1 $xIV &= Binary(Chr($i)) Next $tIVBuffer = DllStructCreate(StringFormat("byte data[%i]", $iBlockLength)) $tIVBuffer.data = $xIV _DebugOut("IV = " & $tIVBuffer.data) EndIf The specific line 3422, the DllStructCreate is creating a new DllStruct variable $tIVBuffer: $tIVBuffer = DllStructCreate(StringFormat("byte data[%i]", $iBlockLength)) A DllStruct variable $tByteBuffer is returned from __CryptoNG_BCryptGetProperty: $tByteBuffer = __CryptoNG_BCryptGetProperty($hEncryptionKey, $CNG_BCRYPT_BLOCK_LENGTH) A copy of that struct a created as $tUlong. I'm not entirely sure why _WinAPI_CopyStruct is used here. Does this function turn the DllStruct into a WinAPI struct format? I think CopyStruct is just a WinAPI call to copy the stuct at the memory location specified by $tByteBuffer. But isn't $tByteBuffer a DllStruct variable? $tUlong = _WinAPI_CopyStruct($tByteBuffer, "ulong value") Then $iBlockLength uses the ulong value of $tUlong. $iBlockLength = $tUlong.value It appears that DllStructCreate for $tIVBuffer uses $iBlockLength as a length for data[?]. $tIVBuffer = DllStructCreate(StringFormat("byte data[%i]", $iBlockLength)) $tIVBuffer.data = $xIV Also I see this reference in __CryptoNG_BCryptGetProperty on line 4880: _DebugOut("$tBuffer = " & $tBuffer.data) There is a .data property used for the DllStruct variable. What is contained in .data? The actual binary data of the struct in memory? Is there a list of other properties that can be accessed from a DllStruct directly? Generally, is my understanding of both examples above correct? I'm trying to understand what's going on, rather than mimicking the code. Again thanks for the help. I'm still studying both UDF's. They are so well organized and written. I especially like how the HTTPAPI API organizes the structs in a global header section. ;======================== ; STRUCTURES ;======================== ;Global HHTP Version Structure Global $__HTTPAPI_gtagHTTP_VERSION = _ "struct;" & _ "ushort MajorVersion;" & _ "ushort MinorVersion;" & _ "endstruct;" ;Global HHTPAPI Version Structure and Constants Global $__HTTPAPI_gtagHTTPAPI_VERSION = _ "struct;" & _ "ushort HttpApiMajorVersion;" & _ "ushort HttpApiMinorVersion;" & _ "endstruct;" And structs within structs: Global $__HTTPAPI_gtagHTTP_DATA_CHUNK_FROM_FRAGMENT_CACHE_EX = _ $__HTTPAPI_gtagHTTP_DATA_CHUNK & _ "struct;" & _ "ushort FragmentNameLength;" & _ ;in bytes not including the NUL "ptr pFragmentName;" & _ ;wstr "endstruct;" Also, I saw the data alignment techniques here: Global $__HTTPAPI_gtagHTTP_DATA_CHUNK = _ "struct;" & _ "int DataChunkType;" & _ "endstruct;" & _ (@AutoItX64 ? "" : "ptr;") ;Union alignment issue found & fixed by Danyfirex Edited June 1, 2021 by swoop Caught my error in understanding line 3422 TheXman 1 Link to comment Share on other sites More sharing options...
swoop Posted June 1, 2021 Author Share Posted June 1, 2021 (edited) Sorry, my bad. I just caught my error in the second example for __CryptoNG_BCryptGetProperty. $tIVBuffer = DllStructCreate(StringFormat("byte data[%i]", $iBlockLength)) $tIVBuffer.data = $xIV This is actually creating the struct variable defined by StringFormat("byte data[%i]", $iBlockLength) So the struct is something like "byte data[10]" In this case, it is not an optional pointer. Edited June 1, 2021 by swoop Link to comment Share on other sites More sharing options...
TheXman Posted June 1, 2021 Share Posted June 1, 2021 (edited) 43 minutes ago, swoop said: I think that means the $tHeader struct is not created nor allocated in memory. We're just creating a struct variable to work with the struct. Correct 43 minutes ago, swoop said: To apply the same idea to my ZeroMQ Dll struct code, if the ZeroMQ DLL functions create existing message structs and gives me back pointers, then I can use the DllStructCreate to do the same as you've done above. Correct again 43 minutes ago, swoop said: It appears that DllStructCreate for $tIVBuffer uses $iBlockLength as a length for data[?]. Correct 43 minutes ago, swoop said: There is a .data property used for the DllStruct variable. What is contained in .data? The actual binary data of the struct in memory? Sort of. "data" is a named member of the struct (not really a property as such - but it can be thought of that way when using dot-notation to access struct members. The same can be done using DllStructGetData/DllStructSetData, but I prefer the dot-notation when possible). Edited June 1, 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...
TheXman Posted June 1, 2021 Share Posted June 1, 2021 (edited) By the way, you should not get caught up with creating or using the callback function in the zmq_msg_init_data() API. It is optional. Since you are creating the data struct, you can either free the resources yourself, or if it is a local variable, it will be freed when the function it is in is done. In AutoIt, most local resources are freed when there are no more references to them. Therefore, when the function that the API call is in is finished, the data struct's memory will be freed also. I actually created a script to test it, along with about 4 or 5 other ZeroMQ APIs and it works as described and expected. I'm off to the gym right now but if you would like to see the test script, then show me what you have done and I will show you the test script later this afternoon (in a few hours) when I return. Edited June 1, 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...
swoop Posted June 1, 2021 Author Share Posted June 1, 2021 (edited) 2 hours ago, TheXman said: By the way, you should not get caught up with creating or using the callback function in the zmq_msg_init_data() API. It is optional. Good suggestion. I'll get the rest of the functions written and tested first. 2 hours ago, TheXman said: In AutoIt, most local resources are freed when there are no more references to them. So, this usually occurs when scope of a function ends. If the data struct is in the global scope, the resources are freed upon exit of the script. Is that correct? I can just let AutoIt handle that garbage collection. Just curious, is there a way to free or destroy that data struct? Something like a _WinAPI_CopyStruct (Creates a duplicate of a specified structure), but for destroying a Struct? Nine said my somevarA = 0 doesn't actually free up that data. Quote It is because you are zeroing the pointer not the struct. Edited June 1, 2021 by swoop Link to comment Share on other sites More sharing options...
Nine Posted June 1, 2021 Share Posted June 1, 2021 Just set the structure to 0 (not the pointers) : $msg = 0 ; this frees the msg struct $data = 0 ; this frees the data struct 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 June 1, 2021 Share Posted June 1, 2021 (edited) @swoop Since it appears that you are really taking the time to learn, I will put my little sample script below (with its output). Ordinarily, I would wait to see some actual effort or for an explicit request. Keep in mind that this is just one way, my way. As with any language, there's usually many ways to say the same thing. The sample script has terse documentation, but hopefully enough to help understand what each block of code is doing. I am hiding it behind the "Show Hidden Contents" banner in case you would rather not be tempted to see it while browsing the topic. Spoiler expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #AutoIt3Wrapper_UseX64=Y #cs 0MQ LibZMQ Github: https://github.com/zeromq/libzmq 0MQ LibZMQ Releases: https://github.com/zeromq/libzmq/releases 0MQ API Reference: http://api.zeromq.org/master:_start #ce #include <Constants.au3> ;Global Constant(s) Const $DEBUGGING = True Const $ZEROMG_DLL_FILE = @ScriptDir & "\libzmq-v142-mt-4_3_4.dll" Const $TAG_ZMQ_MSG_T = "byte msg[64];" ;Global Handle(s) Global $ghZeroMQDll = -1 ;Context Options Const $ZMQ_IO_THREADS = 1, _ $ZMQ_MAX_SOCKETS = 2, _ $ZMQ_SOCKET_LIMIT = 3, _ $ZMQ_THREAD_PRIORITY = 3, _ $ZMQ_THREAD_SCHED_POLICY = 4, _ $ZMQ_MAX_MSGSZ = 5, _ $ZMQ_MSG_T_SIZE = 6, _ $ZMQ_THREAD_AFFINITY_CPU_ADD = 7, _ $ZMQ_THREAD_AFFINITY_CPU_REMOVE = 8, _ $ZMQ_THREAD_NAME_PREFIX = 9 zeromq_test() Func zeromq_test() Local $sVersion = "" Local $vData = "" Local $hContext = -1 Local $tMsg = "", $tData = "" Local $pMsg = 0 Local $iOption = 0, $iOptionValue = 0 ConsoleWrite("====================" & @CRLF) ConsoleWrite("ZeroMQ API Test" & @CRLF) ConsoleWrite("====================" & @CRLF) ;Get and display 0MQ version $sVersion = zmq_version() If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_version ERROR", "DllCall failed with @error = " & @extended) ConsoleWrite("ZeroMQ: Version = " & $sVersion & @CRLF) ;Create a message struct $tMsg = DllStructCreate($TAG_ZMQ_MSG_T) $pMsg = DllStructGetPtr($tMsg) ;Create a msg data struct with data $vData = "ABCDEF" $tData = DllStructCreate(StringFormat("byte data[%i]", BinaryLen($vData))) $tData.data = Binary($vData) ;Initialize a data message zmq_msg_init_data($pMsg, $tData) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_msg_init_data ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: New data msg successfuly initialized" & @CRLF) ;~ $tData = 0 ;Explicitly free data struct memory (not necessary; local resources will be freed when func ends) ;Get a new 0MQ context handle $hContext = zmq_ctx_new() If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_new ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: New context handle successfuly created = " & $hContext & @CRLF) ;Set a context option $iOption = $ZMQ_IO_THREADS $iOptionValue = 3 zmq_ctx_set($hContext, $iOption, $iOptionValue) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_set ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: Context option ZMQ_IO_THREADS successfuly set to " & $iOptionValue & @CRLF) ;Get a context option $iOptionValue = zmq_ctx_get($hContext, $iOption) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_get ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: Context option ZMQ_IO_THREADS successfuly retrieved = " & $iOptionValue & @CRLF) ;Get a context option $iOptionValue = zmq_ctx_get($hContext, $ZMQ_MAX_MSGSZ) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_get ERROR", zmq_strerror(@extended)) ConsoleWrite(StringFormat("ZeroMQ: Context option ZMQ_MAX_MSGSZ successfuly retrieved = %i (0x%x)", $iOptionValue, $iOptionValue) & @CRLF) ;Terminate a 0MQ context handle zmq_ctx_term($hContext) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Error terminating new context handle. - errno = " & @extended) ConsoleWrite("ZeroMQ: Context handle successfuly terminated = " & $hContext & @CRLF) EndFunc ;================================== ; Internal/Helper Functions ;================================== Func get_zmq_dll_handle() ;If no dll handle exists yet If $ghZeroMQDll = -1 Then ;Get global handle to dll $ghZeroMQDll = DllOpen($ZEROMG_DLL_FILE) If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "DllOpen failed") ;Register function to close dll handle on exit OnAutoItExitRegister("close_zmq_dll_handle") If $DEBUGGING Then ConsoleWrite("(DEBUG) ZeroMQ: DLL handle opened." & @CRLF) EndIf ;Return global handle to dll Return $ghZeroMQDll EndFunc Func close_zmq_dll_handle() ;Close global handle DllClose($ghZeroMQDll) If $DEBUGGING Then ConsoleWrite("(DEBUG) ZeroMQ: DLL handle closed" & @CRLF) EndFunc ;==================================== ; ZeroMQ API Function Examples ; - zmq_ctx_new() ; - zmq_ctx_set($hContext, $iOption, $iOptionValue) ; - zmq_ctx_get($hContext, $iOption) ; - zmq_ctx_term($hContext) ; - zmq_errno() ; - zmq_msg_init_data($pMsg, $tData) ; - zmq_strerror($iErrNo) ; - zmq_version() ;==================================== Func zmq_ctx_new() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "handle", "zmq_ctx_new") If @error Then Return SetError(1, @error, 0) ;DllCall failed ElseIf $aResult[0] = 0 Then Return SetError(2, zmq_errno(), 0) ;API call failed EndIf ;Return new 0MQ context handle Return $aResult[0] EndFunc Func zmq_ctx_set($hContext, $iOption, $iOptionValue) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_set", _ "handle", $hContext, _ "int", $iOption, _ "int", $iOptionValue) If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] = -1 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_ctx_get($hContext, $iOption) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_get", _ "handle", $hContext, _ "int", $iOption) If @error Then Return SetError(1, @error, -1) ;DllCall failed ElseIf $aResult[0] = -1 Then Return SetError(2, zmq_errno(), -1) ;API call failed EndIf ;All is good Return $aResult[0] EndFunc Func zmq_ctx_term($hContext) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_term", "handle", $hContext) If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] <> 0 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_errno() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_errno") If @error Then Return SetError(1, @error, -1) ;DllCall failed EndIf ;All is good Return $aResult[0] EndFunc Func zmq_msg_init_data($pMsg, $tData) Local $aResult If DllStructGetSize($tData) = 0 Then Return SetError(-1, 0, False) ;No data ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_msg_init_data", _ "ptr", $pMsg, _ ;msg "ptr", DllStructGetPtr($tData), _ ;data "ulong_ptr", DllStructGetSize($tData), _ ;size "ptr", Null, _ ;ffn "ptr", Null) ;hint If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] <> 0 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_strerror($iErrNo) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "str", "zmq_strerror", _ "int", $iErrNo) If @error Then Return SetError(1, @error, "") ;Return version Return $aResult[0] EndFunc Func zmq_version() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "none", "zmq_version", _ "int*", Null, _ ;Major "int*", Null, _ ;Minor "int*", Null) ;Patch If @error Then Return SetError(1, @error, "?.?.?") ;Return version Return StringFormat("%s.%s.%s", $aResult[1], $aResult[2], $aResult[3]) EndFunc Console Output: ==================== ZeroMQ API Test ==================== (DEBUG) ZeroMQ: DLL handle opened. ZeroMQ: Version = 4.3.4 ZeroMQ: New data msg successfuly initialized ZeroMQ: New context handle successfuly created = 0x00000000007B8750 ZeroMQ: Context option ZMQ_IO_THREADS successfuly set to 3 ZeroMQ: Context option ZMQ_IO_THREADS successfuly retrieved = 3 ZeroMQ: Context option ZMQ_MAX_MSGSZ successfuly retrieved = 2147483647 (0x7fffffff) ZeroMQ: Context handle successfuly terminated = 0x00000000007B8750 (DEBUG) ZeroMQ: DLL handle closed Edited June 2, 2021 by TheXman swoop and jugador 1 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...
swoop Posted June 1, 2021 Author Share Posted June 1, 2021 3 minutes ago, TheXman said: I am hiding it behind the "Show Hidden Contents" banner in case you would rather not be tempted to see it while browsing the topic. I peeked! Thanks for the guidance. I am very grateful. I'm going to apply your way. It's so much better than my first attempt. I see this particular use of DllOpen and DllClose to get a DLL Handle instead of using the DLL filename string in the helper functions. DllOpen($ZEROMG_DLL_FILE) and DllClose($ghZeroMQDll) That's more flexible than just using a global string constant for the filename. Getting the handle can also give an error message if the DLL is missing. Is the following code just added assurance that the DLL handle is closed upon exit? ;Register function to close dll handle on exit OnAutoItExitRegister("close_zmq_dll_handle") I see you also used handle instead of ptr for the $hContext. The handle type appears to be equivalent to void*. I made that mistake as well. Again, thanks for the help! Link to comment Share on other sites More sharing options...
TheXman Posted June 1, 2021 Share Posted June 1, 2021 (edited) 1 hour ago, swoop said: I see this particular use of DllOpen and DllClose to get a DLL Handle instead of using the DLL filename string in the helper functions. From the help file for the DllCall function: If a dll filename is given then the DLL is automatically loaded and then closed at the end of the call. In other words, if you use a DLL handle in your DllCalls, it doesn't need to open/close the DLL file for each DllCall. So if you are going to be doing multiple DllCalls, it's better to use a handle. Both ways work but one is more efficient if you are going to be doing multiple DllCalls using any given DLL file. 1 hour ago, swoop said: Is the following code just added assurance that the DLL handle is closed upon exit? Yes, I like explicitly tidying up as much as possible. The get_zmq_dll_handle() function, which is used by all of the DllCalls, gets and saves a global DLL handle upon its first successful invocation. Also upon the first successful invocation, it registers a function to close the handle upon exit of the script. That way, even if the script is prematurely ended, like with an EXIT statement, the DLL handle will still be explicitly closed. I do this for a lot of handles, like when I'm using SQLite or if I want to make sure that other global resources are freed before exiting the script. All subsequent invocation of get_zmq_dll_handle() just returns the saved global DLL handle. You are correct that it isn't required to close the handle because it will be closed anyway, but I always prefer explicit actions over implicit actions. 1 hour ago, swoop said: I see you also used handle instead of ptr for the $hContext. Internally, there's no difference between a pointer and a handle. Symantically, there's a difference. A pointer is just that, it points to a specific address in memory. A handle is a pointer that points to a resource. So the way I think of it: All handles are pointers, but not all pointers are handles. Edited June 1, 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...
JockoDundee Posted June 1, 2021 Share Posted June 1, 2021 54 minutes ago, TheXman said: Internally, there's no difference between a pointer and a handle. Symantically, there's a difference. A pointer is just that, it points to a specific address in memory. A handle is a pointer that points to a resource. So the way I think of it, all handles are pointers, but not all pointers are handles. Agree with your overall sentiment, but would just mention some handles are not direct pointers to “a specific address in memory”. Like a file handle from FileOpen() will return an small integer which (AFAIK) is a relative offset into another table which has pointers to memory structures. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
TheXman Posted June 1, 2021 Share Posted June 1, 2021 (edited) 10 minutes ago, JockoDundee said: Agree with your overall sentiment, but would just mention some handles are not direct pointers to “a specific address in memory”. I guess I should have been more clear that I was referring to DllCalls & DllStructs, which is the main subject of this topic. In other words, I was speaking at a lower level than AutoIt. But you are absolutely correct. AutoIt uses the term "handle" to point to resources and some of those "handles" are not actually memory pointers - they are more like resource IDs. Edited June 1, 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...
jugador Posted January 8 Share Posted January 8 Try ZeroMQ to connect between server & client using tcp & it work Server.au3 expandcollapse popup#include "ZeroMQ Udf.au3" __zeromq_Server() Func __zeromq_Server() __zmq_Start() Local $h_Context = 0 Local $h_Socket = 0 $h_Context = __zmq_ctx_new() If @error Then __Server_OnExit($h_Context, $h_Socket, "__zmq_ctx_new ERROR: " & __zmq_strerror(@extended)) Local $ZMQ_REP = 4 $h_Socket = __zmq_socket($h_Context, $ZMQ_REP) If @error Then Return __Server_OnExit($h_Context, $h_Socket, "__zmq_socket ERROR: " & __zmq_strerror(@extended)) Local $rc $rc = __zmq_bind($h_Socket, "tcp://*:5555") If @error Then __Server_OnExit($h_Context, $h_Socket, "__zmq_bind ERROR: " & __zmq_strerror(@extended)) RunWait( @AutoItExe & " /AutoIt3ExecuteScript " & '"Client.au3"') Local $t_Msg, $p_Msg __zmq_msg_t($t_Msg, $p_Msg) __zmq_msg_init($p_Msg) $rc = __zmq_msg_recv($p_Msg, $h_Socket, 0) If @error Then __Server_OnExit($h_Context, $h_Socket, "__zmq_msg_send ERROR: " & __zmq_strerror(@extended)) ConsoleWrite('__zmq_msg_recv[byte]: ' & $rc & @crlf) __Server_OnExit($h_Context, $h_Socket, "The End....") EndFunc Func __Server_OnExit(Byref $h_Context, Byref $h_Socket, $o_msg) ConsoleWrite('-> ' & $o_msg & @crlf) If $h_Socket <> 0 Then __zmq_close($h_Socket) If @error Then ConsoleWrite("Socket on close[zmq_close] ERROR: " & __zmq_strerror(@extended) & @crlf) Endif If $h_Context <> 0 Then __zmq_ctx_shutdown($h_Context) If @error Then ConsoleWrite("Context on close[zmq_ctx_shutdown] ERROR: " & __zmq_strerror(@extended) & @crlf) __zmq_ctx_term($h_Context) If @error Then ConsoleWrite("Context on close[zmq_ctx_term] ERROR: " & __zmq_strerror(@extended) & @crlf) EndIf $h_Socket = 0 $h_Context = 0 Exit EndFunc Client.au3 expandcollapse popup#include "ZeroMQ Udf.au3" __zeromq_Client() Func __zeromq_Client() MsgBox(0, 'client', '[Client started]') __zmq_Start() Local $h_Context = 0 Local $h_Socket = 0 $h_Context = __zmq_ctx_new() If @error Then __Client_OnExit($h_Context, $h_Socket, "__zmq_ctx_new ERROR: " & __zmq_strerror(@extended)) Local $ZMQ_REQ = 3 $h_Socket = __zmq_socket($h_Context, $ZMQ_REQ) If @error Then Return __Client_OnExit($h_Context, $h_Socket, "__zmq_socket ERROR: " & __zmq_strerror(@extended)) Local $rc $rc = __zmq_connect($h_Socket, "tcp://localhost:5555") If @error Then __Client_OnExit($h_Context, $h_Socket, "__zmq_connect ERROR: " & __zmq_strerror(@extended)) Local $t_Msg, $p_Msg __zmq_msg_t($t_Msg, $p_Msg) $rc = __zmq_msg_init_data($p_Msg, 'Hello') If @error Then __Client_OnExit($h_Context, $h_Socket, "__zmq_msg_init_data ERROR: " & __zmq_strerror(@extended)) $rc = __zmq_msg_send($p_Msg, $h_Socket, 0) If @error Then __Client_OnExit($h_Context, $h_Socket, "__zmq_msg_send ERROR: " & __zmq_strerror(@extended)) MsgBox(0, 'Client', '__zmq_msg_send[byte]: ' & $rc) $rc = __zmq_disconnect($h_Socket, "tcp://localhost:5555") If @error Then __Client_OnExit($h_Context, $h_Socket, "__zmq_disconnect ERROR: " & __zmq_strerror(@extended)) __Client_OnExit($h_Context, $h_Socket, "From Client The End....") EndFunc Func __Client_OnExit(Byref $h_Context, Byref $h_Socket, $o_msg) MsgBox(0, 'Client', '-> ' & $o_msg) If $h_Socket <> 0 Then __zmq_close($h_Socket) If @error Then MsgBox(0, 'Client', "Socket on close[zmq_close] ERROR: " & __zmq_strerror(@extended) & @crlf) Endif If $h_Context <> 0 Then __zmq_ctx_shutdown($h_Context) If @error Then MsgBox(0, 'Client', "Context on close[zmq_ctx_shutdown] ERROR: " & __zmq_strerror(@extended) & @crlf) __zmq_ctx_term($h_Context) If @error Then MsgBox(0, 'Client', "Context on close[zmq_ctx_term] ERROR: " & __zmq_strerror(@extended) & @crlf) EndIf $h_Socket = 0 $h_Context = 0 Exit EndFunc Link to comment Share on other sites More sharing options...
jugador Posted January 9 Share Posted January 9 @TheXman little query, how to read data using zmq_msg_data pointer? I use your below code.... zmq_msg_init_data($pMsg, $tData) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_msg_init_data ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: New data msg successfuly initialized" & @CRLF) ;~ $tData = 0 ;Explicitly free data struct memory (not necessary; local resources will be freed when func ends) Local $iSize = zmq_msg_size($pMsg) ConsoleWrite("ZeroMQ: byte: " & $iSize & @CRLF) Local $pData = zmq_msg_data($pMsg) ConsoleWrite("ZeroMQ: pointer: " & $pData & @CRLF) How i retrieve the raw data using this given pointer & size? Try DllStruct using the given pointer ($pData) but failed. Link to comment Share on other sites More sharing options...
TheXman Posted January 9 Share Posted January 9 (edited) @jugador 1 hour ago, jugador said: How i retrieve the raw data using this given pointer & size? I would create a struct using DllStructCreate() function and pass it the pointer parameter of $pData. Then reference the struct data as you normally would, using DllstructGetData or with dot-notation. How your reference the data depends on the expected data (binary, string, int, struct, etc). Without more details, it's hard to be more specific. Create struct something like: Reference data as raw binary data $tStruct = DllStructCreate("byte data[" & $iSize & "]", $pData) Reference data as CHAR string: $tStruct = DllStructCreate("char data[" & $iSize & "]", $pData) Reference data as WCHAR string: $tStruct = DllStructCreate("wchar data[" & $iSize & "]", $pData) Reference data as INT: $tStruct = DllStructCreate("int data", $pData) etc... ===================== Reference the "data" of the struct like: DllstructGetData($tStruct, 1) or DllstructGetData($tStruct, "data") or $tStruct.data Edited January 9 by TheXman jugador 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...
jugador Posted January 9 Share Posted January 9 @TheXman I use your code as it is. just add zmq_msg_size & zmq_msg_data to get the binary data. ;Create a msg data struct with data $vData = "ABCDEF" $tData = DllStructCreate(StringFormat("byte data[%i]", BinaryLen($vData))) $tData.data = Binary($vData) ConsoleWrite('+ ' & DllStructGetData($tData, 1) & @crlf) ;~ 0x414243444546 I want to retrieve the Binary data that is ( 0x414243444546 ) using zmq_msg_data pointer. try: $tBinaryBuffer = DllStructCreate("byte data[" & $iSize & "]", $pData) ConsoleWrite('+ ' & DllStructGetData($tBinaryBuffer, 1) & @crlf) ;~ but it return 0x010000000000 https://libzmq.readthedocs.io/en/latest/zmq_msg_data.html Upon successful completion, zmq_msg_data() shall return a pointer to the message content . Link to comment Share on other sites More sharing options...
TheXman Posted January 9 Share Posted January 9 (edited) @jugador 52 minutes ago, jugador said: I use your code as it is You may be using my previous example as a guide, but my previous example did not include functions to retrieve the message size or pointer. So you are asking for help with code that I have not seen and cannot possibly know if it is working correctly. Therefore, I provided you a theoretical answer to a theoretical problem. If you'd like a more specific answer as to why your code is not producing the expected results, then providing an actual example, that I can run, would be most helpful. I don't need a huge example script. I just need the smallest script that I can run that shows the issue you are having. example() Func example() Local $tData = "", _ $tStruct = "" Local $pData = 0 Local $vData = "" Local $iSize = 0 ;Create a msg data struct with data $vData = "ABCDEF" $tData = DllStructCreate(StringFormat("byte data[%i]", BinaryLen($vData))) $tData.data = Binary($vData) ConsoleWrite('+ ' & DllStructGetData($tData, 1) & @crlf) ;~ 0x414243444546 ;Get pointer to data struct and size of struct $pData = DllStructGetPtr($tData) $iSize = DllStructGetSize($tData) ;Get data as binary $tStruct = DllStructCreate(StringFormat("byte data[%i]", $iSize), $pData) ConsoleWrite('+ $tStruct.data = ' & $tStruct.data & @crlf) ; 0x414243444546 ;Get data as a string $tStruct = DllStructCreate(StringFormat("char data[%i]", $iSize), $pData) ConsoleWrite('+ $tStruct.data = ' & $tStruct.data & @CRLF) ;ABCDEF EndFunc Console output: + 0x414243444546 + $tStruct.data = 0x414243444546 + $tStruct.data = ABCDEF Edited January 9 by TheXman jugador 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...
jugador Posted January 9 Share Posted January 9 @TheXman added zmq_msg_size and zmq_msg_data expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #AutoIt3Wrapper_UseX64=Y #cs 0MQ LibZMQ Github: https://github.com/zeromq/libzmq 0MQ LibZMQ Releases: https://github.com/zeromq/libzmq/releases 0MQ API Reference: http://api.zeromq.org/master:_start #ce #include <Constants.au3> ;Global Constant(s) Const $DEBUGGING = True Const $ZEROMG_DLL_FILE = @ScriptDir & "\libzmq-v142-mt-4_3_4.dll" Const $TAG_ZMQ_MSG_T = "byte msg[64];" ;Global Handle(s) Global $ghZeroMQDll = -1 ;Context Options Const $ZMQ_IO_THREADS = 1, _ $ZMQ_MAX_SOCKETS = 2, _ $ZMQ_SOCKET_LIMIT = 3, _ $ZMQ_THREAD_PRIORITY = 3, _ $ZMQ_THREAD_SCHED_POLICY = 4, _ $ZMQ_MAX_MSGSZ = 5, _ $ZMQ_MSG_T_SIZE = 6, _ $ZMQ_THREAD_AFFINITY_CPU_ADD = 7, _ $ZMQ_THREAD_AFFINITY_CPU_REMOVE = 8, _ $ZMQ_THREAD_NAME_PREFIX = 9 zeromq_test() Func zeromq_test() Local $sVersion = "" Local $vData = "" Local $hContext = -1 Local $tMsg = "", $tData = "" Local $pMsg = 0 Local $iOption = 0, $iOptionValue = 0 ConsoleWrite("====================" & @CRLF) ConsoleWrite("ZeroMQ API Test" & @CRLF) ConsoleWrite("====================" & @CRLF) ;Get and display 0MQ version $sVersion = zmq_version() If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_version ERROR", "DllCall failed with @error = " & @extended) ConsoleWrite("ZeroMQ: Version = " & $sVersion & @CRLF) ;Create a message struct $tMsg = DllStructCreate($TAG_ZMQ_MSG_T) $pMsg = DllStructGetPtr($tMsg) ;Create a msg data struct with data $vData = "ABCDEF" $tData = DllStructCreate(StringFormat("byte data[%i]", BinaryLen($vData))) $tData.data = Binary($vData) ;Initialize a data message zmq_msg_init_data($pMsg, $tData) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_msg_init_data ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: New data msg successfuly initialized" & @CRLF) ;~ $tData = 0 ;Explicitly free data struct memory (not necessary; local resources will be freed when func ends) ;~~~~~~~~~~ Local $iSize = zmq_msg_size($pMsg) ConsoleWrite("ZeroMQ: byte: " & $iSize & @CRLF) Local $pData = zmq_msg_data($pMsg) ConsoleWrite("ZeroMQ: pointer: " & $pData & @CRLF) Local $tBinaryBuffer = DllStructCreate("byte data[" & $iSize & "]", $pData) ConsoleWrite('+ ' & DllStructGetData($tBinaryBuffer, 1) & @crlf) ;~~~~~~~~~~ ;Get a new 0MQ context handle $hContext = zmq_ctx_new() If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_new ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: New context handle successfuly created = " & $hContext & @CRLF) ;Set a context option $iOption = $ZMQ_IO_THREADS $iOptionValue = 3 zmq_ctx_set($hContext, $iOption, $iOptionValue) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_set ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: Context option ZMQ_IO_THREADS successfuly set to " & $iOptionValue & @CRLF) ;Get a context option $iOptionValue = zmq_ctx_get($hContext, $iOption) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_get ERROR", zmq_strerror(@extended)) ConsoleWrite("ZeroMQ: Context option ZMQ_IO_THREADS successfuly retrieved = " & $iOptionValue & @CRLF) ;Get a context option $iOptionValue = zmq_ctx_get($hContext, $ZMQ_MAX_MSGSZ) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "zmq_ctx_get ERROR", zmq_strerror(@extended)) ConsoleWrite(StringFormat("ZeroMQ: Context option ZMQ_MAX_MSGSZ successfuly retrieved = %i (0x%x)", $iOptionValue, $iOptionValue) & @CRLF) ;Terminate a 0MQ context handle zmq_ctx_term($hContext) If @error Then Return MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Error terminating new context handle. - errno = " & @extended) ConsoleWrite("ZeroMQ: Context handle successfuly terminated = " & $hContext & @CRLF) EndFunc ;================================== ; Internal/Helper Functions ;================================== Func get_zmq_dll_handle() ;If no dll handle exists yet If $ghZeroMQDll = -1 Then ;Get global handle to dll $ghZeroMQDll = DllOpen($ZEROMG_DLL_FILE) If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "DllOpen failed") ;Register function to close dll handle on exit OnAutoItExitRegister("close_zmq_dll_handle") If $DEBUGGING Then ConsoleWrite("(DEBUG) ZeroMQ: DLL handle opened." & @CRLF) EndIf ;Return global handle to dll Return $ghZeroMQDll EndFunc Func close_zmq_dll_handle() ;Close global handle DllClose($ghZeroMQDll) If $DEBUGGING Then ConsoleWrite("(DEBUG) ZeroMQ: DLL handle closed" & @CRLF) EndFunc ;==================================== ; ZeroMQ API Function Examples ; - zmq_ctx_new() ; - zmq_ctx_set($hContext, $iOption, $iOptionValue) ; - zmq_ctx_get($hContext, $iOption) ; - zmq_ctx_term($hContext) ; - zmq_errno() ; - zmq_msg_init_data($pMsg, $tData) ; - zmq_strerror($iErrNo) ; - zmq_version() ;==================================== Func zmq_ctx_new() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "handle", "zmq_ctx_new") If @error Then Return SetError(1, @error, 0) ;DllCall failed ElseIf $aResult[0] = 0 Then Return SetError(2, zmq_errno(), 0) ;API call failed EndIf ;Return new 0MQ context handle Return $aResult[0] EndFunc Func zmq_ctx_set($hContext, $iOption, $iOptionValue) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_set", _ "handle", $hContext, _ "int", $iOption, _ "int", $iOptionValue) If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] = -1 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_ctx_get($hContext, $iOption) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_get", _ "handle", $hContext, _ "int", $iOption) If @error Then Return SetError(1, @error, -1) ;DllCall failed ElseIf $aResult[0] = -1 Then Return SetError(2, zmq_errno(), -1) ;API call failed EndIf ;All is good Return $aResult[0] EndFunc Func zmq_ctx_term($hContext) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_ctx_term", "handle", $hContext) If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] <> 0 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_errno() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_errno") If @error Then Return SetError(1, @error, -1) ;DllCall failed EndIf ;All is good Return $aResult[0] EndFunc Func zmq_msg_init_data($pMsg, $tData) Local $aResult If DllStructGetSize($tData) = 0 Then Return SetError(-1, 0, False) ;No data ;Call API $aResult = DllCall(get_zmq_dll_handle(), "int", "zmq_msg_init_data", _ "ptr", $pMsg, _ ;msg "ptr", DllStructGetPtr($tData), _ ;data "ulong_ptr", DllStructGetSize($tData), _ ;size "ptr", Null, _ ;ffn "ptr", Null) ;hint If @error Then Return SetError(1, @error, False) ;DllCall failed ElseIf $aResult[0] <> 0 Then Return SetError(2, zmq_errno(), False) ;API call failed EndIf ;All is good Return True EndFunc Func zmq_strerror($iErrNo) Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "str", "zmq_strerror", _ "int", $iErrNo) If @error Then Return SetError(1, @error, "") ;Return version Return $aResult[0] EndFunc Func zmq_version() Local $aResult ;Call API $aResult = DllCall(get_zmq_dll_handle(), "none", "zmq_version", _ "int*", Null, _ ;Major "int*", Null, _ ;Minor "int*", Null) ;Patch If @error Then Return SetError(1, @error, "?.?.?") ;Return version Return StringFormat("%s.%s.%s", $aResult[1], $aResult[2], $aResult[3]) EndFunc Func zmq_msg_data($pMsg) Local $aResult = DllCall(get_zmq_dll_handle(), "ptr", "zmq_msg_data", "ptr", $pMsg) If @error Then Return SetError(1, @error, -1) ;~ DllCall failed Return $aResult[0] ;~ return a pointer to the message content. EndFunc Func zmq_msg_size($pMsg) Local $aResult = DllCall(get_zmq_dll_handle(), "ulong_ptr", "zmq_msg_size", "ptr", $pMsg) If @error Then Return SetError(1, @error, -1) ;~ DllCall failed Return $aResult[0] ;~ return the size of the message content in bytes. EndFunc TheXman 1 Link to comment Share on other sites More sharing options...
TheXman Posted January 9 Share Posted January 9 (edited) @jugador So if you add the lines below to the script that you posted, you get the data as a string, correct? $tBinaryBuffer = DllStructCreate("char data[" & $iSize & "]", $pData) ConsoleWrite('+ ' & DllStructGetData($tBinaryBuffer, 1) & @crlf) This is the output I get: ==================== ZeroMQ API Test ==================== (DEBUG) ZeroMQ: DLL handle opened. ZeroMQ: Version = 4.3.4 ZeroMQ: New data msg successfuly initialized ZeroMQ: byte: 6 ZeroMQ: pointer: 0x0000000000752F70 + 0x414243444546 + ABCDEF ZeroMQ: New context handle successfuly created = 0x0000000000755D90 ZeroMQ: Context option ZMQ_IO_THREADS successfuly set to 3 ZeroMQ: Context option ZMQ_IO_THREADS successfuly retrieved = 3 ZeroMQ: Context option ZMQ_MAX_MSGSZ successfuly retrieved = 2147483647 (0x7fffffff) ZeroMQ: Context handle successfuly terminated = 0x0000000000755D90 (DEBUG) ZeroMQ: DLL handle closed Edited January 9 by TheXman jugador 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