Kip Posted October 15, 2008 Share Posted October 15, 2008 (edited) Hi,I saw this very old post by JPM, about a different kind of DllCall.Jon didnt want to do it, so I did. It's only one function but thats enough _DllCall($vDll, $sFormat, $vParam1, $vParam2, $vParam3, .......)Example + Function:CODEGlobal Const $DLL_MESSAGEBOX = "int MessageBox(hwnd handle, str text, str caption, uint type)"Global Const $DLL_BEEP = "int Beep(int frequency, int duration)"_DllCall("User32.dll", $DLL_MESSAGEBOX, 0, "Message", "Title", 0)_DllCall("Kernel32.dll", $DLL_BEEP, 500, 2000); _DllCall by KipFunc _DllCall($vDll, $sFormat, $vParam1=0, $vParam2=0, $vParam3=0, $vParam4=0, $vParam5=0, $vParam6=0, $vParam7=0, $vParam8=0, $vParam9=0, $vParam10=0, $vParam11=0 _ , $vParam12=0, $vParam13=0, $vParam14=0, $vParam15=0, $vParam16=0, $vParam17=0, $vParam18=0, $vParam19=0, $vParam20=0, $vParam21=0, $vParam22=0, $vParam23=0, $vParam24=0 _ , $vParam25=0, $vParam26=0, $vParam27=0, $vParam28=0, $vParam29=0, $vParam30=0, $vParam31=0, $vParam32=0) $iParams = @NumParams-2 If not $sFormat Then Return $sFunction = StringLeft($sFormat, StringInStr($sFormat,"(")-1) $aFunctionSplit = StringSplit($sFunction," ") Local $sReturnType Local $sFunctionName For $i = 1 to $aFunctionSplit[0] If $aFunctionSplit[$i] Then If Not $sFunctionName Then $sFunctionName = $aFunctionSplit[$i] Else $sReturnType = $sFunctionName $sFunctionName = $aFunctionSplit[$i] ExitLoop EndIf EndIf Next If Not $sFunctionName Then Return If Not $sReturnType Then $sReturnType = "int" $iStart = StringInStr($sFormat,"(") $iEnd = StringInStr($sFormat,")") $sParams = StringMid($sFormat,$iStart+1,$iEnd-$iStart-1) $aParamsSplit = StringSplit($sParams,",") If $sParams Then If $aParamsSplit[0] > $iParams Then $iParams = $aParamsSplit[0] EndIf EndIf Local $aParameters[$iParams+1][2] For $i = 1 to $aParamsSplit[0] $aParamSplit = StringSplit($aParamsSplit[$i]," ") For $j = 1 to $aParamSplit[0] If $aParamSplit[$j] Then $aParameters[$i][0] = $aParamSplit[$j] ExitLoop EndIf Next Next If $iParams > 32 Then Return Local $sFinal For $i = 1 to $iParams If Not $aParameters[$i][0] Then Return $aParameters[$i][1] = Execute("$vParam"&$i) If IsString($aParameters[$i][1]) Then $aParameters[$i][1] = StringReplace($aParameters[$i][1],'"','""') $aParameters[$i][1] = '"'&$aParameters[$i][1]&'"' EndIf $sFinal &= ',"'&$aParameters[$i][0]&'",'&$aParameters[$i][1] Next If IsString($vDll) Then $vDll = StringReplace($vDll,'"','""') $vDll = '"'&$vDll&'"' EndIf $sFinal = "DllCall("&$vDll&',"'&$sReturnType&'", "'&$sFunctionName&'"'&$sFinal&")" Return Execute($sFinal) EndFuncNow you just can copy and paste the syntax of a dll function from MSDN. (You'll still have to change the datatypes though) Edited October 15, 2008 by Kip MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
trancexx Posted October 15, 2008 Share Posted October 15, 2008 (edited) This is really great. I think it will help a lot of people to get them selfs familiar with dll calling (like I would know ). Conversions from windows api types to AutoIt types are needed in order to function more properly, I think. Edited October 15, 2008 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
wraithdu Posted October 15, 2008 Share Posted October 15, 2008 (edited) Cool idea. One change - Local $ret = Execute($sFinal) Return $ret[0] Edited October 15, 2008 by wraithdu Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 Kip, can't you do it without Execute? github.com/jvanegmond Link to comment Share on other sites More sharing options...
Andreik Posted October 15, 2008 Share Posted October 15, 2008 Nice idea. When the words fail... music speaks. Link to comment Share on other sites More sharing options...
JRowe Posted October 15, 2008 Share Posted October 15, 2008 I'm gonna have to play with this one, very neat idea, Kip. Kudos [center]However, like ninjas, cyber warriors operate in silence.AutoIt Chat Engine (+Chatbot) , Link Grammar for AutoIt , Simple Speech RecognitionArtificial Neural Networks UDF , Bayesian Networks UDF , Pattern Matching UDFTransparent PNG GUI Elements , Au3Irrlicht 2Advanced Mouse Events MonitorGrammar Database GeneratorTransitions & Tweening UDFPoker Hand Evaluator[/center] Link to comment Share on other sites More sharing options...
trancexx Posted October 15, 2008 Share Posted October 15, 2008 Cool idea. One change - Local $ret = Execute($sFinal) Return $ret[0]I don't get this ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Kip Posted October 15, 2008 Author Share Posted October 15, 2008 (edited) Kip, can't you do it without Execute?No Cool idea. One change - Local $ret = Execute($sFinal) Return $ret[0]Bad idea. Edited October 15, 2008 by Kip MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 No I'm rewriting this for performance. I hope you don't mind.Also, there's a bug in your code:DllCall(user32.dll,"int", "MessageBox","hwnd",0,"str","Message","str","Title","uint",0)DllCall(kernel32.dll,"int", "Beep","int",500,"int",2000)DLL's are not included in " ". github.com/jvanegmond Link to comment Share on other sites More sharing options...
Kip Posted October 15, 2008 Author Share Posted October 15, 2008 yes they are:$vDll = '"'&$vDll&'"' ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE!EndIf$sFinal = "DllCall("&$vDll&',"'&$sReturnType&'", "'&$sFunctionName&'"'&$sFinal&")"Return Execute($sFinal) MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 yes they are:You're right. Sorry about that. github.com/jvanegmond Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 (edited) Rewritten completely. I'm about to do some speed tests, it should be a lot faster. I'll keep you posted. expandcollapse popupGlobal $mDllLib[1][4] Global Const $DLL_MESSAGEBOX = _DllDefine("user32.dll", "int MessageBox(hwnd handle, str text, str caption, uint type)") Global Const $DLL_BEEP = _DllDefine("kernel32.dll", "int Beep(int frequency, int duration)") _DllCall($DLL_MESSAGEBOX, 0, "AutoIt Rocks", "Manadar says hi!", 0) _DllCall($DLL_BEEP,500,100) ; DllCall rewritten for performance by Manadar ; UDF Starts here: ;Global $mDllLib[1][4] ;; UNCOMMENT THIS LINE IF YOU ARE MOVING THIS CODE INTO A SEPERATE FILE #include <Array.au3> Func _DllDefine($pDll, $pString) $lDim = UBound($mDllLib,1) ReDim $mDllLib[$lDim+1][4] If (IsString($pDll)) Then $mDllLib[$lDim][0] = DllOpen($pDll) If @error Then Return @error EndIf Else $mDllLib[$lDim][0] = $pDll EndIf $lSplit = StringSplit($pString, " (),",0) $mDllLib[$lDim][1] = $lSplit[1] ; return type $mDllLib[$lDim][2] = $lSplit[2] ; functions Dim $n = 0 ; Creates an array with parameter types Dim $lParams[1] For $i = 3 to $lSplit[0] Step 3 $n += 1 ReDim $lParams[$n+1] $lParams[$n] = $lSplit[$i] Next $mDllLib[$lDim][3] = $lParams Return $lDim EndFunc Func _DllCall($pID, $vParam1 = 0, $vParam2 = 0, $vParam3 = 0, $vParam4 = 0, $vParam5 = 0, $vParam6 = 0, $vParam7 = 0, $vParam8 = 0, $vParam9 = 0, $vParam10 = 0, $vParam11 = 0 _ , $vParam12 = 0, $vParam13 = 0, $vParam14 = 0, $vParam15 = 0, $vParam16 = 0, $vParam17 = 0, $vParam18 = 0, $vParam19 = 0, $vParam20 = 0, $vParam21 = 0, $vParam22 = 0, $vParam23 = 0, $vParam24 = 0 _ , $vParam25 = 0, $vParam26 = 0, $vParam27 = 0, $vParam28 = 0, $vParam29 = 0, $vParam30 = 0, $vParam31 = 0, $vParam32 = 0) $lParams = $mDllLib[$pID][3] Switch UBound($lParams)-1 Case 0 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2]) Case 1 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1) Case 2 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2) Case 3 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3) Case 4 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3,$lParams[4],$vParam4) Case 5 Return DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3,$lParams[4],$vParam4,$lParams[5],$vParam5) ; I got bored doing this. Someone continue it please. Case Else SetError(1) return 0 EndSwitch EndFunc Edited October 16, 2008 by Manadar github.com/jvanegmond Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 Try for yourself. The speed difference isn't all that: 10 functions take 1 ms longer. I've written this without Execute though, which is a plus for me. expandcollapse popupGlobal $mDllLib[1][4] Global Const $MANADAR_DLL_BEEP = _DllDefine("kernel32.dll", "int Beep(int frequency, int duration)") Global Const $KIP_DLL_BEEP = "int Beep(int frequency, int duration)" $MANADAR_START = TimerInit() For $i = 0 to 9 _DllCall($MANADAR_DLL_BEEP,500,100) Next $MANADAR_DURATION = TimerDiff($MANADAR_START) $KIP_START = TimerInit() For $i = 0 to 9 _Old_DllCall("Kernel32.dll", $KIP_DLL_BEEP, 500, 100) Next $KIP_DURATION = TimerDiff($KIP_START) MsgBox(0, "", "Time it took for Manadars DllCall: " & $MANADAR_DURATION & @CRLF & _ "Time it took for Kips DllCall: " & $KIP_DURATION) ; DllCall rewritten for performance by Manadar ; UDF Starts here: ;Global $mDllLib[1][4] ;; UNCOMMENT THIS LINE IF YOU ARE MOVING THIS CODE INTO A SEPERATE FILE #include <Array.au3> Func _DllDefine($pDll, $pString) $lDim = UBound($mDllLib,1) ReDim $mDllLib[$lDim+1][4] If (IsString($pDll)) Then $mDllLib[$lDim][0] = DllOpen($pDll) If @error Then Return @error EndIf Else $mDllLib[$lDim][0] = $pDll EndIf $lSplit = StringSplit($pString, " (),",0) $mDllLib[$lDim][1] = $lSplit[1] ; return type $mDllLib[$lDim][2] = $lSplit[2] ; functions Dim $n = 0 ; Creates an array with parameter types Dim $lParams[1] For $i = 3 to $lSplit[0] Step 3 $n += 1 ReDim $lParams[$n+1] $lParams[$n] = $lSplit[$i] Next $mDllLib[$lDim][3] = $lParams Return $lDim EndFunc Func _DllCall($pID, $vParam1 = 0, $vParam2 = 0, $vParam3 = 0, $vParam4 = 0, $vParam5 = 0, $vParam6 = 0, $vParam7 = 0, $vParam8 = 0, $vParam9 = 0, $vParam10 = 0, $vParam11 = 0 _ , $vParam12 = 0, $vParam13 = 0, $vParam14 = 0, $vParam15 = 0, $vParam16 = 0, $vParam17 = 0, $vParam18 = 0, $vParam19 = 0, $vParam20 = 0, $vParam21 = 0, $vParam22 = 0, $vParam23 = 0, $vParam24 = 0 _ , $vParam25 = 0, $vParam26 = 0, $vParam27 = 0, $vParam28 = 0, $vParam29 = 0, $vParam30 = 0, $vParam31 = 0, $vParam32 = 0) $lParams = $mDllLib[$pID][3] Switch UBound($lParams)-1 Case 0 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2]) Case 1 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1) Case 2 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2) Case 3 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3) Case 4 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3,$lParams[4],$vParam4) Case 5 DllCall($mDllLib[$pID][0],$mDllLib[$pID][1],$mDllLib[$pID][2],$lParams[1],$vParam1,$lParams[2],$vParam2,$lParams[3],$vParam3,$lParams[4],$vParam4,$lParams[5],$vParam5) ; I got bored doing this. Someone continue it please. :P Case Else SetError(1) return 0 EndSwitch EndFunc ; _DllCall by Kip Func _Old_DllCall($vDll, $sFormat, $vParam1=0, $vParam2=0, $vParam3=0, $vParam4=0, $vParam5=0, $vParam6=0, $vParam7=0, $vParam8=0, $vParam9=0, $vParam10=0, $vParam11=0 _ , $vParam12=0, $vParam13=0, $vParam14=0, $vParam15=0, $vParam16=0, $vParam17=0, $vParam18=0, $vParam19=0, $vParam20=0, $vParam21=0, $vParam22=0, $vParam23=0, $vParam24=0 _ , $vParam25=0, $vParam26=0, $vParam27=0, $vParam28=0, $vParam29=0, $vParam30=0, $vParam31=0, $vParam32=0) $iParams = @NumParams-2 If not $sFormat Then Return $sFunction = StringLeft($sFormat, StringInStr($sFormat,"(")-1) $aFunctionSplit = StringSplit($sFunction," ") Local $sReturnType Local $sFunctionName For $i = 1 to $aFunctionSplit[0] If $aFunctionSplit[$i] Then If Not $sFunctionName Then $sFunctionName = $aFunctionSplit[$i] Else $sReturnType = $sFunctionName $sFunctionName = $aFunctionSplit[$i] ExitLoop EndIf EndIf Next If Not $sFunctionName Then Return If Not $sReturnType Then $sReturnType = "int" $iStart = StringInStr($sFormat,"(") $iEnd = StringInStr($sFormat,")") $sParams = StringMid($sFormat,$iStart+1,$iEnd-$iStart-1) $aParamsSplit = StringSplit($sParams,",") If $sParams Then If $aParamsSplit[0] > $iParams Then $iParams = $aParamsSplit[0] EndIf EndIf Local $aParameters[$iParams+1][2] For $i = 1 to $aParamsSplit[0] $aParamSplit = StringSplit($aParamsSplit[$i]," ") For $j = 1 to $aParamSplit[0] If $aParamSplit[$j] Then $aParameters[$i][0] = $aParamSplit[$j] ExitLoop EndIf Next Next If $iParams > 32 Then Return Local $sFinal For $i = 1 to $iParams If Not $aParameters[$i][0] Then Return $aParameters[$i][1] = Execute("$vParam"&$i) If IsString($aParameters[$i][1]) Then $aParameters[$i][1] = StringReplace($aParameters[$i][1],'"','""') $aParameters[$i][1] = '"'&$aParameters[$i][1]&'"' EndIf $sFinal &= ',"'&$aParameters[$i][0]&'",'&$aParameters[$i][1] Next If IsString($vDll) Then $vDll = StringReplace($vDll,'"','""') $vDll = '"'&$vDll&'"' EndIf $sFinal = "DllCall("&$vDll&',"'&$sReturnType&'", "'&$sFunctionName&'"'&$sFinal&")" Return Execute($sFinal) EndFunc github.com/jvanegmond Link to comment Share on other sites More sharing options...
YellowLab Posted October 15, 2008 Share Posted October 15, 2008 (edited) I've written this without Execute though, which is a plus for me. Just curious, what is wrong with "Execute"?Thanks,Bob Edited October 15, 2008 by YellowLab You can't see a rainbow without first experiencing the rain. Link to comment Share on other sites More sharing options...
Richard Robertson Posted October 15, 2008 Share Posted October 15, 2008 Because Manadar does things like this Link to comment Share on other sites More sharing options...
Valik Posted October 15, 2008 Share Posted October 15, 2008 Now you just can copy and paste the syntax of a dll function from MSDN.This is simply not true. Anything that takes a string will not work. Anything that uses a structure will not work. Those two aspects alone comprise the majority of the functions in the Windows API. Anything that uses a BOOL will not work since that is also an invalid type.Just curious, what is wrong with "Execute"?In this case there's nothing wrong with using it. In fact this is one of only a handful of actual, legitimate uses for Execute(). The problem Execute() solves in this case is it allows a built-in function to be called with a specific number of parameters not known until run-time. Mandar's solution, while avoiding Execute() arbitrarily enforces a limit to the number of parameters that can be passed to DllCall() effectively eliminating the wrapper function's usefulnesson the more complex API calls. Link to comment Share on other sites More sharing options...
jvanegmond Posted October 15, 2008 Share Posted October 15, 2008 (edited) Just curious, what is wrong with "Execute"?Without going into discussion it is often considered as "bad programming practice" to use Execute, and as such I try to avoid it always.There's not a real topic yet defining why Execute is bad, but we (AutoIt forum and members) have had the discussion many times. I guess we could move the question here: http://www.autoitscript.com/forum/index.php?showtopic=49064 and look for a better explanation.Edit: Never mind. Valik already started. Edited October 15, 2008 by Manadar github.com/jvanegmond Link to comment Share on other sites More sharing options...
Richard Robertson Posted October 15, 2008 Share Posted October 15, 2008 Oh, and for the sake of clarification, I didn't mean that Manadar is a turtle who has sex with other turtles. I meant that he makes images like that (as you can see by it being hosted on his website). Link to comment Share on other sites More sharing options...
Kip Posted October 15, 2008 Author Share Posted October 15, 2008 (edited) This is simply not true.I know, you still have to edit some minor stuff, but it is easier.Edit: Edited first post Edited October 15, 2008 by Kip MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
Valik Posted October 15, 2008 Share Posted October 15, 2008 If editing things to make it work at all is minor in your book then I really would like to know what you consider major. 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