argumentum Posted December 27, 2017 Share Posted December 27, 2017 (edited) From the manual: "DllOpen: Opens a DLL file for use in DllCall." But I see everywhere in the distribution UDFs, no use of it for DllCall(). In the manual, the example is: Local $hDLL = DllOpen("user32.dll") DllCall($hDLL, "int", "MessageBox", "hwnd", 0, "str", "Some text", "str", "Some title", "int", 0) DllClose($hDLL) but what I actually see is the UDFs, is more along the lines of: ; Calling the MessageBox API directly. DllCall("user32.dll", "int", "MessageBox", _ "hwnd", 0, _ ; Handle to the parent window "str", "Some text", _ ; The text of the message box "str", "Some title", _ ; The title of the message box "int", 0) ; Flags for the message box. So, "to DllOpen or not to DllOpen, that is the question." Edited December 27, 2017 by argumentum Danyfirex 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
RTFC Posted December 27, 2017 Share Posted December 27, 2017 (edited) It's a bit like FileWrite, where you can use the filename or a handle you open with FileOpen beforehand. If your call is a one-off then it's overkill to get a handle for it, call it, then close it again. But if you're going to be accessing the dll dozens or hundreds (millions?) of times in your code, it's faster to get a handle once and use that while you need the dll, then close it once. And of course, the UDFs are mostly single call affairs (GDI+ is an exception), so the only way to ensure the handle gets closed (no memory leak) is to open and close it directly per UDF call. Edited December 27, 2017 by RTFC Danyfirex 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
argumentum Posted December 27, 2017 Author Share Posted December 27, 2017 2 minutes ago, RTFC said: if you're going to be accessing the dll dozens or hundreds (millions?) of times ..yes, I see no time difference between one way or the other. I the DllCall remark is : If a dll filename is given then the DLL is automatically loaded and then closed at the end of the call. If you want to manually control the loading and unloading of the DLL then you should use DllOpen() and DllClose() and use a handle instead of a filename in this function. I came to this question while looking at <Date.au3> and the question popped into my head: why is this not with a handle to "kernel32.dll" as is constantly called. =/ Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
RTFC Posted December 27, 2017 Share Posted December 27, 2017 (edited) 1) The dll itself may already be in virtual memory due to earlier calls (and you'd probably need heavy-duty benchmarking to perceive a notable difference anyhow) 2) avoid memory leaks due to dangling handles Edited December 27, 2017 by RTFC Earthshine and argumentum 2 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
argumentum Posted December 27, 2017 Author Share Posted December 27, 2017 (edited) 25 minutes ago, RTFC said: 1) The dll itself may already be in virtual memory due to earlier calls So AutoIt loads the DLL when first called, and closes it when the program/script closes ? Maybe system DLLs ( those in use since Win95 ) are accounted for within AutoIt but otherwise it'd be good to Open and close manually ? Or there are types of DLLs, like those used for GDI+, that need the Open/Close functionality due to the "type" of DLL, and I say "type" with quote marks because, I don't know much, other than to script ( somewhat ) if there is a UDF already in place Edited December 27, 2017 by argumentum clarify Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Earthshine Posted December 27, 2017 Share Posted December 27, 2017 (edited) you missed the more important #2. He suggests closing handles you open. This is the best practice, now and forever, you can sing that like at church..... in unmanaged code, you had darned well better clean up after yourself. With .NET managed stuff, it does the garbage cleanup for you, but if you are allocating memory and resources, you should free it when you exit or don't need it anymore https://www.autoitscript.com/autoit3/docs/functions/DllClose.htm Edited December 27, 2017 by Earthshine Danyfirex 1 My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
argumentum Posted December 27, 2017 Author Share Posted December 27, 2017 14 minutes ago, Earthshine said: you missed the more important #2. He suggests closing handles you open AutoIt closes those DLLs ( on exit or right after the call, no clue yet ), BUT there are those that need to be handled manually like GDI or Richedit. My question is when and why use DllOpen() or when is just impractical. 16 minutes ago, Earthshine said: in unmanaged code, you had darned well better clean up after yourself I know that I should always clean after myself. My mother told me that, and my father reinforced the knowledge with his slipper shoes Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Developers Jos Posted December 27, 2017 Developers Share Posted December 27, 2017 (edited) 11 minutes ago, argumentum said: My question is when and why use DllOpen() or when is just impractical. Thought that question was answered already by @RTFC. When you use DllCall() with a filename, AutoIt3 will perform DllOpen();DllCall();DllCLose() for you. This is fine when doing a single DllCall, but when you want to do a thousand DllCall as fast as possible you can imagine it is faster to one DllOpen() at the beginning, then do all the DllCall's using the openen filehandle and then close it..... right? Same counts for FileRead/FileWrite operations. Jos Edited December 27, 2017 by Jos Earthshine 1 SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
argumentum Posted December 27, 2017 Author Share Posted December 27, 2017 10 minutes ago, Jos said: but when you want to do a thousand DllCall as fast as possible you can imagine it is faster to one DllOpen() well, not that noticeable: Global $kernel32dll = DllOpen("kernel32.dll") OnAutoItExitRegister("closeDlls") Func closeDlls() DllClose($kernel32dll) EndFunc ;==>closeDlls Local $times[4][2000] $count = 1 $times[0][0] = 0 $lastcount = -9 $tt = TimerInit() While $count < 2000 $times[0][$count] = TimerDiff($tt) $times[1][$count] = _MSec() ; AutoIt Open/Close DLL ;~ $times[1][$count] = _MSec($kernel32dll) ; managed Open/Close DLL $times[2][$count] = @error $times[3][$count] = @extended If $times[0][$count] <> $times[0][$count - 1] Then $count += 1 WEnd For $i = 1 To $count - 1 If $times[1][$i] = $times[1][$i - 1] Then ContinueLoop ConsoleWrite('TimerDiff, ' & $i & ' @MSEC = ' & StringFormat("%5.5f, %d", $times[0][$i], $times[1][$i]) & " - " & $times[2][$i] & "," & $times[3][$i] & @CRLF) ;### Debug Console Next ConsoleWrite('TimerDiff, ' & $count - 1 & ' @MSEC = ' & StringFormat("%5.5f, %d", $times[0][$count - 1], $times[1][$count - 1]) & @CRLF) ;### Debug Console Exit Func _MSec($kernel32dll = "kernel32.dll") Local $stSystemTime = DllStructCreate("ushort varYear;ushort varMon;ushort varDofW;ushort varDay;ushort varHour;ushort varMin;ushort varSec;ushort varMsec") DllCall($kernel32dll, 'none', 'GetSystemTime', 'ptr', DllStructGetPtr($stSystemTime)) ; UTC time Return SetError(@error, @extended, StringFormat('%03d', DllStructGetData($stSystemTime, 8))) EndFunc ;==>_MSec that is why I'm posting the question. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Developers Jos Posted December 27, 2017 Developers Share Posted December 27, 2017 I've stated what needed to be stated on the matter and when you don't notice the difference then do as you please. Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
argumentum Posted December 27, 2017 Author Share Posted December 27, 2017 (edited) 1 hour ago, Jos said: then do as you please Don't get me wrong. There is a difference of some porcentage* and yes, it is faster to do the DllOpen. The question is a bit deeper. The <Date.au3> does not use DllOpen() - I was looking at that when my question popped up - and it, in my view, should use it, then again, is impractical for a call or 2 the user would make, to handle the "IsItLoaded" and when to close it. So I was looking for a deeper explanation to, when and why, other than "you can go either way, just clean house once you're done". There are those DLLs that must be properly handled or the script will crash. There must be a reason. That is all. * PS: I added this later for anyone that in the future would like to see how much faster, tho, this should not be about speed alone. Spoiler Global $stSystemTime = DllStructCreate("ushort varYear;ushort varMon;ushort varDofW;ushort varDay;ushort varHour;ushort varMin;ushort varSec;ushort varMsec") Global $kernel32dll = DllOpen("kernel32.dll") OnAutoItExitRegister("closeDlls") Func closeDlls() DllClose($kernel32dll) EndFunc ;==>closeDlls Local $nLoopCount = 10000 ; <--- change this if you feel like it Local $nTestCount = 10 ; <--- change this if you feel like it Local $times[4][$nLoopCount] Local $av[$nTestCount][2] $av[0][0] = UBound($av) - 1 For $n = 1 To $av[0][0] $tt = TimerInit() For $count = 1 To $nLoopCount - 1 $times[0][$count] = TimerDiff($tt) $times[1][$count] = _MSec() ; AutoIt Open/Close DLL Next $av[$n][0] = Round($times[0][$nLoopCount - 1]) ConsoleWrite('AutoIt Open/Close DLL = TimerDiff, ' & $av[$n][0] & " .ms" & @TAB) ;### Debug Console $tt = TimerInit() For $count = 1 To $nLoopCount - 1 $times[0][$count] = TimerDiff($tt) $times[1][$count] = _MSec($kernel32dll) ; managed Open/Close DLL Next $av[$n][1] = Round($times[0][$nLoopCount - 1]) ConsoleWrite('managed Open/Close DLL = TimerDiff, ' & $av[$n][1] & " .ms ( " & Round((1 - ($av[$n][1] / $av[$n][0])) * 100) & " % faster )" & @CRLF) ;### Debug Console Next Exit Func _MSec($kernel32dll = "kernel32.dll") DllCall($kernel32dll, 'none', 'GetSystemTime', 'ptr', DllStructGetPtr($stSystemTime)) ; UTC time Return SetError(@error, @extended, StringFormat('%03d', DllStructGetData($stSystemTime, 8))) EndFunc ;==>_MSec Edited December 27, 2017 by argumentum added test bed Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
RTFC Posted December 27, 2017 Share Posted December 27, 2017 31 minutes ago, argumentum said: AutoIt closes those DLLs ( on exit or right after the call If called with the filename, the dll is closed immediately after the call; if called with the earlier obtained handle it stays open until closed by the user or AFAIK upon normal script termination (although this is sloppy practice ,and you shouldn't rely on it). However, in case of abnormal termination/crash, you may have a memory leak. 34 minutes ago, argumentum said: there are those that need to be handled manually like GDI I would suggest you call the GDI Startup function (because there are version-specific settings involved) rather than opening that dll directly. But in general, any dll can be opened and closed on a call-by-call basis using the filename or user-opened and closed separately. Regarding filename-based calls in the standard includes such as <Date.au3>, remember that these UDFs are meant to function on their own, without users needing to be aware of handles to be obtained first or closed after. So by sacrificing a little processing speed, calling a dll function can be made a single action, which makes the task much easier for beginners, and more empowering. 58 minutes ago, argumentum said: my father reinforced the knowledge with his slipper shoes Well, I guess you'll have to be thankful he didn't have mountaineering boots with ice crampons close to hand. argumentum 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
Earthshine Posted December 27, 2017 Share Posted December 27, 2017 (edited) Think mega thousands of calls. It makes a diff. Everyone starts as a beginner but you can’t be a beginner forever you need to learn how to program correctly Many many years ago I read a book called writing structured basic and it changed my life Edited December 27, 2017 by Earthshine My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
argumentum Posted December 28, 2017 Author Share Posted December 28, 2017 27 minutes ago, Earthshine said: Many many years ago I read a book called writing structured basic I started with basic on an Apple II back in 1984. After that I studied microprocessors (1985), Then quit, whent fix planes. then years later started with TPascal 5.5. I have an idea. Picked up coding back in 2005 looked at Delphi ...but i found AutoIt. I should have opened this topic in a chat forum but I did it here. Is not help I wanted, but educated views on why, how, etc.@RTFC answered the question. Repeatedly. I was looking for ... go figure, clarification on why the UDF was written as such. Thank you @Earthshine for your participation. And since i'm in a thank you letter, thanks @Jos for your input, I added a piece of code to show the speed gain ( %5 on average in my test PC ). I'm happy Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
RTFC Posted December 28, 2017 Share Posted December 28, 2017 9 hours ago, argumentum said: Is not help I wanted, but educated views on why, how, etc. I never had you pegged as a beginner, argumentum, and I reckon you posed an interesting, valid question (definitely not mere chat). Investigating and questioning(!) the source code is a good way of gaining a deeper understanding; I try to get a peek under the hood myself when I get the chance. So don't put yourself down, okay? argumentum 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O 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