Jump to content
Sign in to follow this  
MarkRobbins

Real OOP with AutoIt? Meet JSAIO...

Recommended Posts

MarkRobbins

I've been thinking about this for the last couple of weeks, and I've finally got around to putting together a proof of concept.

As far as OOP goes, Javascript is a pretty damn good language -- very flexible, but lets look at some code. Here is a two button form for AutoIt written in Javascript.

var $=this;
var hgui;
this.MsgHandler_=function (m){
  if (m==$.AutoIt.GUI_EVENT_CLOSE) {
    $.AutoIt.GUIDelete(hgui);
    return true;
  }else if (m==button1) {
    $.AutoIt.Run("notepad.exe");
  }else if (m==button2) {
    alert('Thanks from a javascript alert box!');
  }
  return false;
}
var button1,button2;
function Example1(){
  var msg;
  hgui=$.AutoIt.GUICreate("My Gui",400,500);
  button1=$.AutoIt.GUICreateButton("Run Notepad",10,10,200,30);
  button2=$.AutoIt.GUICreateButton("Press Me",10,40,200,30);
  $.AutoIt.GUISetState($.AutoIt.SW_SHOW,hgui);
}
Example1();

This code would reside in an external file and be called by AutoIt.

I've created a framework in AutoIt using AutoItObject that is just big enough to make this code work.

Basically I am creating an AutoItObject, tacking on some core AutoIt functions and constants, and sending it off to play in Javascript land. There is much more to be tacked on.

Other than this AutoItObject being a proxy for AutoIt functionality, there is a Javascript COM object into which the javascript file is loaded, and a message loop that calls back into the javascript.

The framework is 300 lines of code.

Before I extend this, I want to know if AutoIt ALREADY has a COM object I that I can use like this. But I am thinking that even if it does, this hand-coded way would be better because you can make the calls pass objects instead of parameters.

Here is the framework:

#include <AutoItObject.au3>
#include <GUIConstants.au3>


Global $thisfile=@ScriptFullPath;
Global $logg=$thisfile&".log.txt";

Global $jsfile=$thisfile&".js";
;e C:\batch\borg\TestJsaio.au3.js

;fret not, you do not need, will be a no-op if not exist
Global Const $snarl="C:\batch\Snarl_CMD.exe";

; need script exit for AIO shutdown
OnAutoItExitRegister("EvtScriptExit")
_AutoItObject_StartUp()

; error handler
Global $oError
$oError = ObjEvent("AutoIt.Error", "_ErrFunc")

; JScript Com globals
Global $_ComObj_proxy
Global $_com
Global $_Js
JScriptInit()
;;;;;;;;;;;;;;;;;;;;;;;;;;done inits

;;;;;;;;;;; begin framework

; set up a mini framework of AutoIt Functions/constants and stick them on an object
Global $AutoItForCom=_AutoItObject_Create();
;_AutoItObject_AddMethod(ByRef $oObject, $sName, $sAutoItFunc, $fPrivate = False)
_AutoItObject_AddMethod($AutoItForCom,"GUICreate","GUICreate_AI")
_AutoItObject_AddMethod($AutoItForCom,"GUISetState","GUISetState_AI")
_AutoItObject_AddMethod($AutoItForCom,"GUIGetMsg","GUIGetMsg_AI")
_AutoItObject_AddMethod($AutoItForCom,"GUIDelete","GUIDelete_AI")
_AutoItObject_AddMethod($AutoItForCom,"MsgBox","MsgBox_AI")
_AutoItObject_AddMethod($AutoItForCom,"GuiCreateButton","GuiCreateButton_AI")
_AutoItObject_AddMethod($AutoItForCom,"Run","Run_AI")
;_AutoItObject_AddProperty(ByRef $oObject, $sName, $iFlags = $ELSCOPE_PUBLIC, $vData = "")
_AutoItObject_AddProperty($AutoItForCom, "SW_SHOW", $ELSCOPE_PUBLIC+$ELSCOPE_READONLY, @SW_SHOW)
_AutoItObject_AddProperty($AutoItForCom, "GUI_EVENT_CLOSE", $ELSCOPE_PUBLIC+$ELSCOPE_READONLY, $GUI_EVENT_CLOSE)


;;; here are the tie-ins that the object will call
Func GUICreate_AI($me,$title,$width,$height)
  #forceref $me
  ;GUICreate ( "title" [, width [, height [, left [, top [, style [, exStyle [, parent]]]]]]] )
  Local $rv=GUICreate($title,$width,$height)
  Return $rv
EndFunc
Func GUISetState_AI($me,$flag,$hwnd)
  #forceref $me
  ;GUISetState ( [flag [, winhandle]] )
  Local $rv=GUISetState($flag,HWnd($hwnd));need to covert Int32
  Return $rv
EndFunc
Func GUIGetMsg_AI($me,$advanced)
  #forceref $me
  Local $rv= GUIGetMsg ($advanced)
  Return $rv
EndFunc

Func GUIDelete_AI($me,$winhandle)
  #forceref $me
  Local $rv=GUIDelete($winhandle)
  Return $rv
EndFunc

Func MsgBox_AI($me,$flag,$title,$text)
  #forceref $me
  ;MsgBox ( flag, "title", "text" [, timeout [, hwnd]] )
  Local $rv=MsgBox($flag,$title,$text)
  Return $rv
EndFunc

Func GUICreateButton_AI($me,$text,$left,$top,$width=Default,$height=Default,$style=Default,$exstyle=Default)
  #forceref $me
  ;GUICtrlCreateButton ( "text", left, top [, width [, height [, style [, exStyle]]]] )
  Local $rv=GUICtrlCreateButton ( $text, $left, $top, $width, $height, $style, $exstyle)
  Return $rv
EndFunc

Func Run_AI($me,$program,$wkdir=Default,$show_flag=Default,$opt_flag=Default)
  #forceref $me
  ;Msg2("run",$program)
  Local $rv;
  If False Then
  ElseIf @NumParams==2 Then
    $rv=Run($program)
  ElseIf @NumParams==3 Then
    $rv=Run($program,$wkdir)
  ElseIf @NumParams==4 Then
    $rv=Run($program,$wkdir,$show_flag)
  ElseIf @NumParams==5 Then
    $rv=Run($program,$wkdir,$show_flag,$opt_flag)
  EndIf
  ;Run ( "program" [, "workingdir" [, show_flag [, opt_flag]]] )
  ;Local $rv=Run($program,$wkdir,$show_flag,$opt_flag)
  Return $rv
EndFunc
;;;;;;;;;;;;;;;; end of tie-ins

;;;;;;;;;; setup JScript COM obj
Global $jso=NewComObj()

; import our AutoIt Proxy into the jso
$jso.set("AutoIt", $AutoItForCom)

; read our javascript file
Global $ftext=FileRead($jsfile)

; set the file text up as a Main function
$jso.set_function("Main", "", $ftext)

; need to run our message loop in autoit code, but pass it back to JS land here
$jso.set_function("MsgHandler", "m", "return eval('this.MsgHandler_(m)');")

; hold on to your britches...
; this call will run through the js file and the file must do a setup and have a callback MsgHandler_
$jso.Main()

;; Message Loop
Local $end_if_true
Local $m
  While True
    $m=GUIGetMsg(0)
    $end_if_true=$jso.MsgHandler($m)
    ;Msg($end_if_true);
    If $end_if_true Then
      ExitLoop
    EndIf
  WEnd
Exit

;; the only thing worth looking at below this point is the _ComObj_init and friends
;;;;;;;;;;;;;;;functions
Func EvtScriptExit()
  ;Msg("EvtScriptExit")
  _AutoItObject_Shutdown()
  ;_logline('EvtScriptExit')
  ;If IsObj($MidiMgr) Then
  ;  $MidiMgr.Terminate()
  ;EndIf
EndFunc

Func Msg($s)
  MsgBox(0,$thisfile,$s)
EndFunc
Func Msg2($t,$s)
  MsgBox(0,$t,$s)
EndFunc


Func logclear()
  FileDelete($logg)
EndFunc

Func _logline($line)
  logline($line)
EndFunc

Func logline($line)
  Local $fh1=FileOpen($logg,1);
  If $fh1<>-1 Then
    FileWriteLine($fh1,$line)
    FileClose($fh1)
  EndIf
EndFunc

Func logsnarl($line)
  logerr($line)
  snarl(10,'Fatal Error',$line)
EndFunc

Func snarl($i,$t,$s)
  If Not FileExists($snarl) Then
    Return
  EndIf
  $s1=StringReplace($s,'"',"'")
  $t1=StringReplace($t,'"',"'")
  $cmd=$snarl&' snShowMessage '&$i&' "'&$t1&'" "'&$s1&'"';
  Run($cmd)
EndFunc

;;;;js utils
; #FUNCTION# ==================================================================
; Name      : _ComObj_init
; Description  : Creates MS Windows Script control and deploy it as proxy for
;               AutoIt COM object binding.
; Syntax      : _ComObj_init([$VBScriptSupport = false])
; Parameter : $VBScriptSupport
;               By default JScript doesn't have alert() function, it is provided
;               by browser's window object.
;               We can emulate this using VBScript's MsgBox function, which is
;               performance hog because we need another ScriptControl instance.
;               Other advantage is to be able to execute other VBScript's methods
;               within function via vb.Eval() method.
;               This feature is disabled by default.
; =============================================================================
Func _ComObj_init ($VBScriptSupport = false)
  Local $_Script
  $_Script = ObjCreate("ScriptControl")
  $_Script.Language = "JScript"
  $_Script.Timeout = 60000
  ;$_Script.AddCode("var $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()")
  ;a[a.length]=i;
  ;function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}
  Local $more= _
  "$.get=function(k){return $[k]};" & _
  "$.has=function(n){" & _
  "  for (var i in this){" & _
  "    if (i!=n){" & _
  "      continue;" & _
  "    }" & _
  "    if (!this.hasOwnProperty(i)){" & _
  "      continue;" & _
  "    }" & _
  "    if (typeof(this[i])=='function'){" & _
  "      continue;" & _
  "    }" & _
  "    return true;" & _
  "  };" & _
  "  return false;" & _
  "};" & _
  "$.keys=function(){" & _
  "  var a=[];" & _
  "  for (var i in this){" & _
  "    if (this.hasOwnProperty(i)){" & _
  "      if (typeof(this[i])!='function'){" & _
  "        a[a.length]=i;" & _
  "      }" & _
  "    }" & _
  "  };" & _
  "  return a;" & _
  "};" & _
  "$.set2=function(){" & _
  "  for(var x=0;x<arguments.length-1;x+=2){" & _
  "    this[arguments[x]]=arguments[x+1]" & _
  "  }" & _
  "};" & _
  "Array.prototype.item=function(n){" & _
  "  return this[n];" & _
  "};" & _
  "Array.prototype.has=function(v){" & _
  "  for(x=0;x<this.length;x++){" & _
  "    if(this[x]==v){return true;}" & _
  "  }" & _
  "  return false;" & _
  "};" & _
  "Array.prototype.asString=function(d){" & _
  "  var s='';" & _
  "  for(x=0;x<this.length;x++){" & _
  "    if(s==''){s=this[x];}else{s+=d+this[x];}" & _
  "  }" & _
  "  return s;" & _
  "};"
  $_Script.AddCode("var $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};"&$more&"$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()")
  If $VBScriptSupport = true Then $_Script.Run("set_vbscript", ObjCreate("ScriptControl"))
  Return $_Script
EndFunc
; =============================================================================

Func NewComObj()
  Local $com
  While True
    $com=$_com.new_object("")
    Sleep(30)
    If IsObj($com) Then
      ExitLoop
    EndIf
  WEnd
  Sleep(30)
  Return $com
EndFunc

Func JScriptInit()
  $_ComObj_proxy = _ComObj_init(true)
  $_com = $_ComObj_proxy.Run("get_proxy")
  $_Js = $_com.new_object("")
  $_Js.set_function("AIOSetProperty","o,n,v","o[n]=v;")
EndFunc

Func JS_SetProp()
  $_Js = $_com.new_object("")
  $_Js.set_function("AIOSetProperty","o,n,v","o[n]=v;")
  Return $_Js;
EndFunc

My main questions are...

  1. Why doesn't this already exist, and where is it? and...
  2. Why doesn't this already exist -- what wall am I headed for?

:bike::nuke::ermm:>_<

Edited by MarkRobbins

Share this post


Link to post
Share on other sites
MarkRobbins

What are all of the concepts that a language needs to be considered object oriented?

 

While you can 'do' OOP in any language, it can be very painful without support. When you think about it, OOP is about making miniature programs, self-contained and (as much as possible) unaware of the outside world.

Many OOP languages are strongly typed, to prevent you from sticking square pegs in round holes, and catching those mistakes at compile time.

Javascript is 'duck typed', meaning its objects are fluid and it is up to the programmer to decide if a particular object 'quacks like a duck'.

This is done by inspecting the object to see if it has a particular property or interface.

The main thing an OOP language must support is heritability, Javascript does a reasonable job of this but it does fall short in some sense, you have to boilerplate a lot of the heritability mechanism yourself.

Bright points of Javascript are:

  • Functions are objects, can be passed
  • It has a cool binding mechanism, where functions declared within functions can access variables within the enclosing scope. Its hard to explain, but once you get it, its very useful
  • Objects are dynamic, and act like hash tables
  • It has a very powerful Eval()
  • Objects can be made up on the fly, no formal declarations or 'class makers' needed
  • It has reflection, you can iterate through an object
  • Its the most popular scripting language in the world

Compared to AutoIt, Javascript will:

  • Get rid of the Globals nightmare, probably possible to write a very complex program with just a single global
  • Allow Case Sensitive identifiers (which some will hate)
  • Get rid of $ on identifiers (which I will LOVE)
  • Provide potential code libraries to be used from the web (typecastjs.org), though many of these are web based, they could be ported
  • Get rid of the parameter nightmare, just pass objects
  • Dynamically create functions, objects and 'code' with Eval()
  • Offer Easy Timers - SetInterval, SetTimeout
  • Provides an easy, well established plugin-mechanism
  • Base types (Number,String,Object,Array,Date,Bool) can be extended

 

For a great lecture on Js ...

Share this post


Link to post
Share on other sites
jaberwacky

"Functions are objects, can be passed"

"Get rid of $ on identifiers (which I will LOVE)" 

I'm hoping that a later version of AutoIt will provide this.

"It has a cool binding mechanism, where functions declared within functions can access variables within the enclosing scope. Its hard to explain, but once you get it, its very useful"

I think those are called closures.

OK, so basically, not real oop in autoit but rather java oop in autoit?

Edited by jaberwocky6669

Share this post


Link to post
Share on other sites
Mat

Javascript is the most popular scripting language in the world? Most used perhaps, but only because its the only choice for client side web apps. Doesn't mean its a good language.

Share this post


Link to post
Share on other sites
MarkRobbins

OK, so basically, not real oop in autoit but rather java oop in autoit?

 

Some would claim that java is TOO oop-y. Execution in the Kingdom of Nouns

Javascript!=Java

Its a common misconception that Js is not real oop, its just not classical oop ala C++ and the like.

Share this post


Link to post
Share on other sites
MarkRobbins

Javascript is the most popular scripting language in the world? Most used perhaps, but only because its the only choice for client side web apps. Doesn't mean its a good language.

<script type="text/vbscript">

Do you know of a better language for scripting? I mean language in terms of language features, not libraries.

I think its a good language, though it does have some flaws. For a not-good language, one would have a hard time explaining the rise of Js on the server side.

Share this post


Link to post
Share on other sites
LateArrival

Forgive me for being somewhat critical but I struggle to see how shoehorning another language into autoit is a good idea.

I would much prefer Autoit or AutoitObject to evolve to be a fully fledged OOP language rather than masquerade it to something that it is not. I love autoit for its directness and simplicity in achieving tasks that would otherwise take you a lot of time to get through in another language.

At the same time my 10-20,000 lines of structured code (not anymore) can use the oop treatment.

So I would ideally prefer for Autoit or AIO to evolve to provide better OOP plumbing (i.e. events etc.) stuff you find in C# and .NET (there you go I said it). If found myself building similar “frameworks” that look like this:

#include 'System.au3'

#include 'System.Collections.au3'

#include 'System.ComponentModel.au3'

#include 'System.Diagnostics.au3'

#include 'System.Data.au3'

#include 'System.Messaging.au3'

#include 'System.Drawing.au3'

#include 'System.IO.au3'

#include 'System.Windows.au3'

#include 'System.Windows.Automation.au3'

#include 'System.Windows.Controls.au3'

#include 'System.Windows.Forms.au3'

#include 'System.Windows.Input.au3'

You can guess what’s in there and what they are supposed to do but I say “frameworks” because in reality it’s a mickey mouse attempt to dress up win api or au3 functions so that they behave like .net. It worked for a while but before too long you run into all sort of other issues.

Having been through this loop I really think it’s a waste of time. There is language that does this already. Its called C# and it runs on a framework that dos all this already and its called .NET and you can buy some thing like DevExpress or similar to sex it up.  

Autoit is still great. Just a few days ago it helped me sort through  150,000 images and save the day for a pretty major retailer all from code found in the help files. Thank you very much. I love Autoit but I am gonna have to give up trying to make it look and work like .NET J

Edited by LateArrival

Share this post


Link to post
Share on other sites
Mat

Apparently the Node.js creator chose javascript because it had no io conventions so he could come up with his funky event based system, that made it so popular. Outside of web development, does javascript have many uses?

Python and ruby have pretty large feature sets. They are both used far more often than javascript for server side programming (and not because they've been around for longer like php). Python I know has most (if not all) the features listed above are there, and there are plenty more as well.

Personally I'd say lots of language features doesn't make a good language, and neither does being flexible. To me, a good language is something like C#, where if you gave 2 C# programmers the same task, their code would look very similar (and not because they are restricted by the language).

Edit: I hope I'm not sounding too cynical about your project. Nothing personal, I just don't like javascript. Probably because I was forced to use it in a couple of web development projects.

Edited by Mat

Share this post


Link to post
Share on other sites
MarkRobbins

Forgive me for being somewhat critical but I struggle to see how shoehorning another language into autoit is a good idea.

 

I think of it this way. On the language front, AutoIt is lacking, but on the library front it is pretty good. Somone at Netscape once remarked that Windows was just a bag of iffy drivers... which at the time, was kinda fair for an insult. So if we look at AutoIt and see it as a so-so language that has a nice bunch of calls... and those calls can be pretty easily clipped onto a COM object -- why would you stay in the language?

Your point about DotNet is well taken, but not even C# is Javascript. Its all about target size, do you want an elephant gun or a shotgun. Javascript gives informality and quick prototyping. I guess my point is that heavier armor has its cost.

To be fair, the objections that come to my mind would be the continuity and coding split, and the question of debugging. I guess my question for you is, why do you do AutoIt and not DotNet? Whats wrong with the best of both worlds?

That is, if it can be done. This is just a probe, I really didn't expect so much poo-pooing. Did AutoItObject receive that reception?

Share this post


Link to post
Share on other sites
MarkRobbins
 

 

 

Outside of web development, does javascript have many uses?

ECMAScript is basis for ActionScript, which is Flex and Flash, both are not confined to the web and are used to create rich GUI desktop apps.

 

I'd say lots of language features doesn't make a good language, and neither does being flexible

Javascript has many, many flaws. But something has to be said about a language that is so flexible that its mistakes can be rectified ad-hoc.

 

if you gave 2 C# programmers the same task, their code would look very similar

 

Good thing for a production environment for sure.

I think your comments were pretty restrained for someone who dislikes javascript. I will ask the same question to you -- why not just develop in C# instead of AutoIt? I don't want to sound snarky, but shouldn't we all have a good answer to that? There must be a reason, and wouldn't that reason be better off in a language that supports OO?

 

Share this post


Link to post
Share on other sites
LateArrival

 Its all about target size, do you want an elephant gun or a shotgun. I guess my point is that heavier armor has its cost.

 

I guess in my case I need an elephant with a machine gun!

A lot of the low level stuff like handling windows, controls, trays, ini files - if you care for that - or hotkeys are not very accessible in WPF or are very counter-intuitive to work with.Do-able but a royal pain. On the other hand, wiring sophisticated GUIs together in AI is also doable but also a royal pain. I mean who wants to register WM_something to handle control events in 2013.

So there is no happy medium as I see it. Enough people have build some of the 'missing' features in WPF over the years so rather than trying to turn AI into something it is not perhaps the best course of action is to invest time in building up the features one needs in C#/WPF (or similar). I could be wrong but attempting to do the opposite  may be quite a huge task and there are always lots of people with varying needs and you can never keep everybody happy.

To be honest it would be too much for me to presume what is right or not for AI since I am new here and I have very healthy respect for anybody who can produce a language and run it successfully over many years. Anyway wasn't poo poing your idea but I just come to think that AI is a pretty good script language to automate windows applications. That is it I think...The rest is just mismanaged or unrealistic expectations (on my part at least).

Share this post


Link to post
Share on other sites
Mat

why not just develop in C# instead of AutoIt? I don't want to sound snarky, but shouldn't we all have a good answer to that? There must be a reason, and wouldn't that reason be better off in a language that supports OO?

I do. I do hardly any AutoIt scripting any more, apart from for very small desktop apps and utilities. For GUI programming, I could still write a GUI in AutoIt from scratch faster than I can do it in visual studio with the designer (and certainly a lot faster than I could do it in C# source code). AutoIt I could write a few hundred lines of script in notepad on someone elses pc, run it with a single standalone executable, and it will work first time (well... most of the time anyway). 

For me, C#, C++, AutoIt and python cover all my needs. None of them are perfect, I don't think a one-language-fits-all solution is possible.

But anyway. Don't let my grumbling stand in your way. Language development is great fun, its something I've had an interest in for years.

Share this post


Link to post
Share on other sites
LateArrival

To Mat 

Btw if I got this right do you take:

 

43 38 48 31 30 4e 34 4f 32 with 43 31 32 48 32 32 4F 31 31 or without?

Share this post


Link to post
Share on other sites
MarkRobbins

I've done some timing tests.

The message loop has to reside in AI and call into JSCOM using an eval.

1000 such calls take 626ms

Direct calls, without eval, into JSCOM

1000 such calls take 728ms (it is weird that eval is faster)

Calling an empty function on the AutoIt AutoItObject (calling out to autoit)

1000 such calls take 69ms

For direct speed comparisons of the languages...

100k loops of addition x=x+1 in AI take 174ms, in JSCOM take 12ms - 1450% faster

10k loops of string concatenation s=s&' '  in AI take 97ms, in JSCOM take 7ms - 1385% faster

100k loops of calling an empty function in AI take 559ms, in JSCOM take 64ms - 873% faster

 

Share this post


Link to post
Share on other sites
BrewManNH

 

I've done some timing tests.

 

 

For direct speed comparisons of the languages...

100k loops of addition x=x+1 in AI take 174ms, in JSCOM take 12ms - 1450% faster

10k loops of string concatenation s=s&' '  in AI take 97ms, in JSCOM take 7ms - 1385% faster

100k loops of calling an empty function in AI take 559ms, in JSCOM take 64ms - 873% faster

 

Not sure how you did the timing tests, but for me 100K "x += 1" gives me 44ms, string concatenation $s &= " " gives me 60ms, and calling an empty function 100K times gives me 104ms, using beta 3.3.9.12. In 3.3.8.1 I get 27ms, 64ms, and 68ms respectively. All things considered, the speed difference isn't all that bad, considering interpreted languages and all.

 


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
MarkRobbins

 

Not sure how you did the timing tests, but for me 100K "x += 1" gives me 44ms, string concatenation $s &= " " gives me 60ms, and calling an empty function 100K times gives me 104ms, using beta 3.3.9.12. In 3.3.8.1 I get 27ms, 64ms, and 68ms respectively. All things considered, the speed difference isn't all that bad, considering interpreted languages and all.

 

 

 

I don't know how you can say that about the speed diff, they are both interpreted. On my planet any difference over 2x is quite considerable. The addition loop executes in 0.06 the time, Concat 0.07, and empty fn in 0.1  -- those are huge.

 

Here are the AI Tests

;loop additions
#cs
$time=TimerInit()
Global $end=100*1000
Global $x,$y=1
For $x=1 To $end
  $y=$y+1
Next
Global $t1
$t1=TimerDiff($time);174
Msg($t1)
Exit
#ce

;loop concat
#cs
$time=TimerInit()
Global $end=10*1000
Global $x,$y=''
For $x=1 To $end
  $y=$y&'x'
Next
Global $t1
$t1=TimerDiff($time);97
Msg($t1)
Exit
#ce

;loop empty fn
#cs
Func EmptyFn($x)
EndFunc
$time=TimerInit()
Global $end=100*1000
Global $x,$y=''
For $x=1 To $end
  EmptyFn(0)
Next
Global $t1
$t1=TimerDiff($time);559
Msg($t1)
Exit
#ce

Intel Xeon E5 2620

Share this post


Link to post
Share on other sites
Mat

To Mat 

Btw if I got this right do you take:

 

43 38 48 31 30 4e 34 4f 32 with 43 31 32 48 32 32 4F 31 31 or without?

Nope. I don't like them sweet. I like them hot and black :)

Share this post


Link to post
Share on other sites
MarkRobbins

Eval is not good.

 

It is the js eval I have to use if I calling into JSCOM with the msg loop, otherwise it hangs...

$jso.set_function("MsgHandler", "m", "return eval('this.MsgHandler_(m)');")

So the call looks like

Local $end_if_true
Local $m
  While True
    $m=GUIGetMsg(0)
    $end_if_true=$jso.MsgHandler($m)
    ;Msg($end_if_true);
    If $end_if_true Then
      ExitLoop
    EndIf
  WEnd
Exit

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • Bilgus
      By Bilgus
      ; NetFirewallPolicy2 COM UDF Library for AutoIt3
      ; AutoIt Version : 3.3.14.5
      ; Description ...: Windows Firewall Policy2 Interface, Provides access to the firewall policy for Windows Vista+
      Including Test Script 
      UDF:
      Test Script:
       
    • Bilgus
      By Bilgus
      I was Playing around With AutoIt this evening and wondered how hard it would be to get typeinfo like the COM Viewers do only using AutoIt
      Turns out it was pretty easy.
      A Few Notes:
      CAarray info is unfinished I didn't have any objects to test it on so I left it Limited.
      The Object must have IDispatch exposed (ITypeInfo is derivative)
      Its Just a proof of concept Run with it but don't carry scissors
      ITypeInfoCOM.au3
      ITypeInfoTest.au3
       
      Output IWebBrowserApp
       
      Output ObjCreate(MediaPlayer.MediaPlayer.1)
       
    • Bilgus
      By Bilgus
       IGroupPolicyObject interface
      ;;IGroupPolicyObject #RequireAdmin #include-once #include <WinAPIConstants.au3> ; $S_OK #include <WinAPIReg.au3> ;_WinAPI_GetRegKeyNameByHandle Global Enum $GPO_SECTION_ROOT = 0x0, $GPO_SECTION_USER, $GPO_SECTION_MACHINE Global Enum $GPO_OPEN_LOAD_REGISTRY = 0x1, $GPO_OPEN_READ_ONLY Global Enum $GPO_OPTION_DISABLE_USER = 0x1, $GPO_OPTION_DISABLE_MACHINE Global Enum $GPOTypeLocal = 0x0, $GPOTypeRemote, $GPOTypeDS, $GPOTypeLocalUser, $GPOTypeLocalGroup Global Const $sCLSID_GroupPolicyObject = "{EA502722-A23D-11D1-A7D3-0000F87571E3}" Global Const $sIID_IGroupPolicyObject = "{EA502723-A23D-11D1-A7D3-0000F87571E3}" Global Const $dtag_IGroupPolicyObject = _ "New hresult(wstr;wstr;dword);" & _ ; Creates a new GPO in the Active Directory with the specified display name. "OpenDSGPO hresult(wstr;dword);" & _ ; Opens the specified GPO and optionally loads the registry information. "OpenLocalMachineGPO hresult(dword);" & _ ; Opens the default GPO for the computer and optionally loads the registry information. "OpenRemoteMachineGPO hresult(wstr;dword);" & _ ; Opens the default GPO for the specified remote computer and optionally loads the registry information. "Save hResult(bool;bool;ptr;ptr);" & _ ; Saves the specified registry policy settings to disk and updates the revision number of the GPO. "Delete hresult();" & _ ; Deletes the GPO. "GetName hResult(wstr;int);" & _ ; Retrieves the unique name for the GPO. "GetDisplayName hResult(wstr;int);" & _ ; Retrieves the display name for the GPO. "SetDisplayName hresult(wstr);" & _ ; Sets the display name for the GPO. "GetPath hResult(wstr;int);" & _ ; Retrieves the path to the GPO. "GetDSPath hresult(dword;wstr;int);" & _ ; Retrieves the Active Directory path to the root of the specified GPO section. "GetFileSysPath hresult(dword;wstr;int);" & _ ; Retrieves the file system path (UNC format) to the root of the specified GPO section. "GetRegistryKey hresult(dword;handle);" & _ ; Retrieves a handle to the root of the registry key for the specified GPO section. "GetOptions hResult(dword*);" & _ ; Retrieves the options for the GPO. "SetOptions hresult(dword;dword);" & _ ; Sets the options for the GPO. "GetType hResult(dword*);" & _ ; Retrieves type information for the GPO being edited. "GetMachineName hResult(wstr;int);" & _ ; Retrieves the computer name of the remote GPO. "GetPropertySheetPages hresult(ptr;uint*);" ; Retrieves the property sheet pages associated with the GPO. Test() Func Test() Local $iResult Local $oIGroupPolicy Local $aGpoType[5] = ["Local", "Remote", "Active Directory", "LocalUser", "LocalGroup"] $oIGroupPolicy = ObjCreateInterface($sCLSID_GroupPolicyObject, $sIID_IGroupPolicyObject, $dtag_IGroupPolicyObject) While True If Not IsObj($oIGroupPolicy) Then ConsoleWrite("Failed To Retrieve Interface") $iResult = $E_NOINTERFACE ExitLoop Else ConsoleWrite("Success: " & ObjName($oIGroupPolicy, 1) & @CRLF) EndIf Local $sLoc, $sPath, $sName, $iType $tKey = DllStructCreate("handle hKey") $iResult = $oIGroupPolicy.OpenLocalMachineGPO(BitOR($GPO_OPEN_LOAD_REGISTRY, $GPO_OPEN_READ_ONLY)) If $iResult <> $S_OK Then ExitLoop $iResult = $oIGroupPolicy.GetDisplayName($sLoc, 65535) If $iResult <> $S_OK Then ExitLoop $iResult = $oIGroupPolicy.GetName($sName, 65535) If $iResult <> $S_OK Then ExitLoop ConsoleWrite($sLoc & " : " & $sName & @CRLF) $iResult = $oIGroupPolicy.GetPath($sPath, 65535) If $iResult <> $S_OK Then ExitLoop $iResult = $oIGroupPolicy.GetType($iType) If $iResult <> $S_OK Then ExitLoop ConsoleWrite($sPath & @CRLF) $iResult = $oIGroupPolicy.GetType($iType) If $iResult <> $S_OK Then ExitLoop ConsoleWrite("Type: " & $aGpoType[$iType] & @CRLF) $iResult = $oIGroupPolicy.GetRegistryKey($GPO_SECTION_USER, DllStructGetPtr($tKey)) If $iResult <> $S_OK Then ExitLoop ConsoleWrite(_WinAPI_GetRegKeyNameByHandle(DllStructGetData($tKey, "hKey")) & @CRLF) ExitLoop WEnd Return SetError($iResult, 0, ($iResult = $S_OK)) EndFunc ;==>Test Note: Not well tested..
    • guinness
      By guinness
      Just trying out the latest version of AutoIt and thinking more functional
      #include <Array.au3> ; Example ; An example of filtering, mapping and reducing arrays, using a function reference. ; This is similiar to how it would be done in the likes of JavaScript ; i.e. more functional (declarative) than procedural (imperative) ; Filter example Local $aiFilteredBefore[] = [1, 2, 3, 50, 30, 40, 20, 30] Local $aiFilteredAfter = _ArrayFilter($aiFilteredBefore, GtrThan30) _ArrayDisplay($aiFilteredAfter, '_ArrayFilter::') ; Map example Local $aiMappedBefore[] = [1, 2, 3, 4, 5, 6, 7, 8, 9] Local $aiMappedAfter = _ArrayMap($aiMappedBefore, MultiplyByTwo) _ArrayDisplay($aiMappedAfter, '_ArrayMap::') ; Reduce example ; Sum all values in the array Local $aiReducedBefore[] = [1, 2, 3, 50, 30, 40, 20, 30] ConsoleWrite('_ArrayReduce:: ' & _ArrayReduce($aiReducedBefore, SumValues) & @CRLF) ; Passing an empty array, will return the initial value; otherwise, sets @error to 4 ; if no initial value is defined Local $aEmpty[] = [] ConsoleWrite('_ArrayReduce:: ' & _ArrayReduce($aEmpty, SumValues, 0) & @CRLF) ; Array callback functions (for the examples only) Func GtrThan30($iValue) Return $iValue > 30 EndFunc ;==>GtrThan30 Func MultiplyByTwo($iValue, $iIndex, $aiArray) ; Notice how the function is called with the optional arguments "index" and "original array" ConsoleWrite('Index:: ' & $iIndex & ', Array:: ' & _ArrayToString($aiArray) & @CRLF) Return $iValue * 2 EndFunc ;==>MultiplyByTwo Func SumValues($a, $b) Return $a + $b EndFunc ;==>SumValues ; Functions ; The callback function is invoked with fn(value, [index, [array]]) Func _ArrayFilter($avArray, $hFunc) If Not IsArray($avArray) Then ; Null is more appropriate than returning the likes of -1 or an empty array Return SetError(1, 0, Null) EndIf If Not IsFunc($hFunc) Then Return SetError(2, 0, Null) EndIf Local Const $iLength = UBound($avArray) Local $avFiltered[$iLength] If $iLength = 0 Then Return $avFiltered EndIf Local $iIndex = 0 For $i = 0 To $iLength - 1 Local $bIsFiltered = __ArrayCall($hFunc, 3, $avArray[$i], $i, $avArray) If @error Then Return SetError(@error, @extended, Null) ElseIf $bIsFiltered Then $avFiltered[$iIndex] = $avArray[$i] $iIndex += 1 EndIf Next ReDim $avFiltered[$iIndex] Return $avFiltered EndFunc ;==>_ArrayFilter ; The callback function is invoked with fn(value, [index, [array]]) Func _ArrayMap($avArray, $hFunc) If Not IsArray($avArray) Then ; Null is more appropriate than returning the likes of -1 or an empty array Return SetError(1, 0, Null) EndIf If Not IsFunc($hFunc) Then Return SetError(2, 0, Null) EndIf Local Const $iLength = UBound($avArray) Local $avMapped[$iLength] If $iLength = 0 Then Return $avMapped EndIf For $i = 0 To $iLength - 1 $avMapped[$i] = __ArrayCall($hFunc, 3, $avArray[$i], $i, $avArray) If @error Then Return SetError(@error, @extended, Null) EndIf Next Return $avMapped EndFunc ;==>_ArrayMap ; The callback function is invoked with fn(current, value, [index, [array]]) Func _ArrayReduce($avArray, $hFunc, $vInitial = Default) If Not IsArray($avArray) Then ; Null is more appropriate than returning the likes of -1 or an empty array Return SetError(1, 0, Null) EndIf If Not IsFunc($hFunc) Then Return SetError(2, 0, Null) EndIf Local $bHasInitial = @NumParams >= 3 Local $iLength = UBound($avArray) If $iLength = 0 Then If Not $bHasInitial Then Return SetError(4, 0, Null) EndIf Return $vInitial EndIf For $i = 0 To $iLength - 1 If $bHasInitial Then $vInitial = __ArrayCall($hFunc, 3, $vInitial, $avArray[$i], $i, $avArray) If @error Then Return SetError(@error, @extended, Null) EndIf Else $bHasInitial = True $vInitial = $avArray[$i] EndIf Next Return $vInitial EndFunc ;==>_ArrayReduce Func __ArrayCall($hFunc, $iError, $vArg1 = Default, $vArg2 = Default, $vArg3 = Default, $vArg4 = Default) Local Const $CALL_ERROR = 0xDEAD Local Const $CALL_EXTENDED = 0xBEEF Local $vRet = Call($hFunc, $vArg1) If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then $vRet = Call($hFunc, $vArg1, $vArg2) If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then $vRet = Call($hFunc, $vArg1, $vArg2, $vArg3) If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then $vRet = Call($hFunc, $vArg1, $vArg2, $vArg3, $vArg4) If @error = $CALL_ERROR And @extended = $CALL_EXTENDED Then ; The function exists, but there is no appropriate function signature Return SetError($iError, 0, Null) EndIf EndIf EndIf EndIf Return SetError(@error, @extended, $vRet) EndFunc ;==>__ArrayCall  
    • Fenzik
      By Fenzik
       Hello all"
      I have curious problem with com object implementation of Sapi 5.1.
      In some cases }Some Voice engines] the metods for retrieve the voice parameters fails with error :Member not exists:.
      But the Retrieved Voice object can speak the given text, so It exists and work.
      Example of this type of Engine can be this one: http://download.kobavision.be/KobaSpeech3/KobaSpeech 3 With Vocalizer Serena - English (Great Britain).exe (can work as demo)
      So my question is> Is there some way to workaround or solve this issue?
      What i tryed:
      1. Typical use of Sapi.spvoice object:
      $oMyError = ObjEvent("AutoIt.Error","MyErrFunc"); Install a custom error handler
       
        $spvoice = ObjCreate("sapi.spvoice")
      for $voice in $spvoice.getvoices()
        msgbox(0, "Voice", $voice.getdescription())
      next
      Func MyErrFunc()
      $HexNumber = hex($oMyError.number, 8)
      Msgbox(0,"","We intercepted a COM Error !" & @CRLF &"Number is: " & $HexNumber & @CRLF &"Windescription is: " & $oMyError.windescription)
      SetError(1)
      Endfunc

      2. Implement workaround based on Nvda Screen reader sapi5 Library at https://github.com/nvaccess/nvda/blob/master/source/synthDrivers/sapi5.py
      Thys code in Pascal should work, so i tryed to reproduce it in Autoit.
      Pascal code just as example:
                   SOTokens:=SpVoice.GetVoices('','');
                   for i:=0 to SOTokens.Count-1 do
                   try
                        SOToken:=SOTokens.Item(I); s:=SOToken.GetDescription(0);
      end
      In Autoit I tryed it like this:
      $oMyError = ObjEvent("AutoIt.Error","MyErrFunc"); Install a custom error handler
        $spvoice = ObjCreate("sapi.spvoice")
      for $i = 0 to $spvoice.getvoices.count-1
      $name = $spvoice.getvoices.item($i).getdescription
      msgbox(0,"Voice", $name)
      next
      Func MyErrFunc()
      $HexNumber = hex($oMyError.number, 8)
      Msgbox(0,"","We intercepted a COM Error !" & @CRLF &"Number is: " & $HexNumber & @CRLF &"Windescription is: " & $oMyError.windescription)
      SetError(1)
      Endfunc
      Both of this methods returning same Error ("Member not exists.").
      Thanks a lot for help.
      Znefyg
×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.