Kip 5 Report post 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 Dutch postcode & address API. Share this post Link to post Share on other sites
trancexx 905 Report post 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 Share this post Link to post Share on other sites
wraithdu 69 Report post Posted October 15, 2008 (edited) Cool idea. One change - Local $ret = Execute($sFinal) Return $ret[0] Edited October 15, 2008 by wraithdu Share this post Link to post Share on other sites
jvanegmond 297 Report post Posted October 15, 2008 Kip, can't you do it without Execute? github.com/jvanegmond Share this post Link to post Share on other sites
Andreik 52 Report post Posted October 15, 2008 Nice idea. When the words fail... music speaks Share this post Link to post Share on other sites
JRowe 6 Report post 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] Share this post Link to post Share on other sites
trancexx 905 Report post Posted October 15, 2008 Cool idea. One change - Local $ret = Execute($sFinal) Return $ret[0]I don't get this ♡♡♡ . eMyvnE Share this post Link to post Share on other sites
Kip 5 Report post 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 Dutch postcode & address API. Share this post Link to post Share on other sites
jvanegmond 297 Report post 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 Share this post Link to post Share on other sites
Kip 5 Report post Posted October 15, 2008 yes they are:$vDll = '"'&$vDll&'"' ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE!EndIf$sFinal = "DllCall("&$vDll&',"'&$sReturnType&'", "'&$sFunctionName&'"'&$sFinal&")"Return Execute($sFinal) Dutch postcode & address API. Share this post Link to post Share on other sites
jvanegmond 297 Report post Posted October 15, 2008 yes they are:You're right. Sorry about that. github.com/jvanegmond Share this post Link to post Share on other sites
jvanegmond 297 Report post 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 Share this post Link to post Share on other sites
jvanegmond 297 Report post 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 Share this post Link to post Share on other sites
YellowLab 0 Report post 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. Share this post Link to post Share on other sites
Richard Robertson 186 Report post Posted October 15, 2008 Because Manadar does things like this Share this post Link to post Share on other sites
Valik 471 Report post 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. Share this post Link to post Share on other sites
jvanegmond 297 Report post 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 Share this post Link to post Share on other sites
Richard Robertson 186 Report post 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). Share this post Link to post Share on other sites
Kip 5 Report post 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 Dutch postcode & address API. Share this post Link to post Share on other sites
Valik 471 Report post 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. Share this post Link to post Share on other sites