Jump to content

Writing my first UDF as learning exercise -- general beginner coaching on exception handling & usability?


Recommended Posts

Hello, I'm more or less a layman to programming, only experience is with Autoit, and am completely unfamiliar with the general practices of Object-Oriented languages.

As an exercise, I'm creating my first UDF that sort of emulates Objects via built-in Autoit functions.

I know it's completely terrible with ill-advised abuses of the language, it's just purely for the purpose of exploration as well as trying to learn what coding an UDF that is usable by other people should entail. Please don't hesitate to point out spots where it's total heresy to unintended uses of functionalities, I have some guesses as to which ones are considered bad but it's nice to get some confirmation of _how_ and why it's bad, as an opportunity for learning an anti-example

Here is what I have for the UDF so far, it's really simplistic and it's coded assuming that the user knows exactly what the functions expect, without any sort of error or exception handling:

Func _ObjBuild(ByRef Const $arr)
      Local $size = UBound($arr, 1)+1    
      Local $self[$size][3], $def = "PTR self;"
      For $i=1 to $size-1
;          $def = $def & "PTR " & $arr[$i-1][0] & ";"
          $def = $def & "PTR " & $arr[$i-1] & ";"
      Next
      $self[0][0] = DllStructCreate($def)
      $self[0][1] = "self"
      $self[0][2] = Null
      DllStructSetData($self[0][0], $self[0][1], Ptr(0))
      For $i=1 to $size-1
          $self[$i][0] = Null       ; $arr[$i-1][1]
          $self[$i][1] = $arr[$i-1] ; $arr[$i-1][0]
          $self[$i][2] = Null       ; $arr[$i-1][2]
          DllStructSetData($self[0][0], $self[$i][1], Ptr($i))
      Next
    Return $self
EndFunc

Func _ObjClone(ByRef Const $arr)
     Local $size = UBound($arr, 1), $def = ""
     For $i=0 to $size-1
         $def = $def & "PTR " & $arr[$i][1] & ";"
     Next
     Local $newarr[$size][3]
     $newarr[0][0] = DllStructCreate($def)
     $newarr[0][1] = $arr[0][1]
     $newarr[0][2] = $arr[0][2]
     DllStructSetData($newarr[0][0], $newarr[0][1], Ptr(0))
     For $i=1 to $size-1
         $newarr[$i][0]=$arr[$i][0]
         $newarr[$i][1]=$arr[$i][1]
         $newarr[$i][2]=$arr[$i][2]
         DllStructSetData($newarr[0][0], $newarr[$i][1], Ptr($i))
     Next
   Return $newarr
EndFunc

Func _ObjSet(ByRef $arr, Const ByRef $key, Const ByRef $val, Const $type=Null)
     Local $index = DllStructGetData($arr[0][0], $key)
     If $index Then
        $arr[$index][0] = $val
     Else
        Local $size = UBound($arr, 1)+1, $def = ""
        ReDim $arr[$size][3]
        $arr[$size-1][0]=$val
        $arr[$size-1][1]=$key
        $arr[$size-1][2]=$type
        For $i=0 to $size-1
            $def = $def & "PTR " & $arr[$i][1] & ";"
        Next
        $arr[0][0] = DllStructCreate($def)
        For $i=0 to $size-1
            DllStructSetData($arr[0][0], $arr[$i][1], Ptr($i))
        Next
     EndIf
EndFunc

Func _ObjGet(ByRef $self, Const ByRef $name, Const $args=Null)
     Local $index = DllStructGetData($self[0][0], $name)
     Local $func=$self[$index][0], $type=$self[$index][2]
     Local $exec="$func"
    Switch $type
      Case True
           $exec = $exec & "($self"
           If IsArray($args) Then
              For $i = 0 to UBound($args)-1
                  If $i=0 Then $exec = $exec & ","
                  $exec = $exec & "$args[" & String($i) & "]"
                  If $i<UBound($args)-1 Then $exec = $exec & ","
              Next
           EndIf
           $exec = $exec & ")"
      Case False
           $exec = $exec & "("
           If IsArray($args) Then
              For $i = 0 to UBound($args)-1
                  $exec = $exec & "$args[" & String($i) & "]"
                  If $i<UBound($args)-1 Then $exec = $exec & ","
              Next
           EndIf
           $exec = $exec & ")"
    EndSwitch
    Return Execute($exec)
EndFunc

Func _ObjArg($arg1=Null, $arg2=Null, $arg3=Null, $arg4=Null, $arg5=Null, $arg6=Null, $arg7=Null, $arg8=Null)
     Local $retArr[@NumParams]
     If @NumParams Then
        For $i=1 to @NumParams
            $retArr[$i-1] = Execute("$arg" & String($i))
        Next
     EndIf
     return $retArr
EndFunc

Here is an example of how it might be used:

#include "objUDF.au3"

ExampleUDFUsage()

Func ExampleUDFUsage()

     Local $class = ["time","position","velocity","acceleration"]
     Local $obj = _ObjBuild($class)

     Local $pos = [420,69,100]
     Local $vel = [320,270,0]
     Local $acc = [0,-200,0]
     _ObjSet($obj, "time", 0)
     _ObjSet($obj, "position", $pos)
     _ObjSet($obj, "velocity", $vel)
     _ObjSet($obj, "acceleration", $acc)
     _ObjSet($obj, "next_pos", Calc_Kinematics, True)
     _ObjSet($obj, "dist", DistanceFromPoint, True)
     _ObjSet($obj, "quit", ExitProgram, False)

     $time = _ObjGet($obj, "time")
     $pos = _ObjGet($obj, "position")
     $vel = _ObjGet($obj, "velocity")
     MsgBox(0, "Initial State t=" & $time, "Position: " & $pos[0] & ", " & $pos[1] & ", " & $pos[2] & @CRLF & "Velocity: " & $vel[0] & ", " & $vel[1] & ", " & $vel[2])

     Local $nowtime, $lasttime=0, $epoch=TimerInit()
     Do
         $nowtime = TimerDiff($epoch)
         AdvancePhysicsState($obj, ($nowtime-$lasttime)*0.001)
         $lasttime = $nowtime
         $time = _ObjGet($obj, "time")
         $pos = _ObjGet($obj, "position")
         $vel = _ObjGet($obj, "velocity")
     Until 7=MsgBox(4, "State: t=" & $time, "Position: " & $pos[0] & ", " & $pos[1] & ", " & $pos[2] & @CRLF & "Velocity: " & $vel[0] & ", " & $vel[1] & ", " & $vel[2] & @CRLF & @CRLF & "Calculate next step?")
     $time = _ObjGet($obj, "time")
     $pos = _ObjGet($obj, "position")
     $vel = _ObjGet($obj, "velocity")
     MsgBox(0, "Final State t=" & $time, "Position: " & $pos[0] & ", " & $pos[1] & ", " & $pos[2] & @CRLF & "Velocity: " & $vel[0] & ", " & $vel[1] & ", " & $vel[2])
     MsgBox(0, "Distance From Starting Point", _ObjGet($obj, "dist", _ObjArg(420,69,100)))
     _ObjGet($obj, "quit")
EndFunc

Func LoopPhysics(ByRef $obj)
EndFunc

Func AdvancePhysicsState(ByRef $obj, $dt)
     _ObjGet($obj, "next_pos", _ObjArg($dt))
EndFunc

Func DistanceFromPoint(ByRef $self, $x, $y, $z)
     Local $pos = _ObjGet($self, "position")
     Local $dx = $pos[0]-$x
     Local $dy = $pos[1]-$y
     Local $dz = $pos[2]-$z
     Return Sqrt($dx*$dx + $dy*$dy + $dz*$dz)
EndFunc

Func Calc_Kinematics(ByRef $self, $dt)
     Local $time = _ObjGet($self, "time")
     Local $pos = _ObjGet($self, "position")
     Local $vel = _ObjGet($self, "velocity")
     Local $acc = _ObjGet($self, "acceleration")
     $time += $dt
     For $i=0 to Ubound($pos)-1
         $pos[$i] += ( (0.5 * $acc[$i] * $dt * $dt) + ($vel[$i] * $dt) )
     Next
     For $i=0 to Ubound($vel)-1
         $vel[$i] += ($acc[$i]*$dt)
     Next
     _ObjSet($self, "time", $time)
     _ObjSet($self, "position", $pos)
     _ObjSet($self, "velocity", $vel)
EndFunc

Func ExitProgram()
     MsgBox(0,"Bye","See Ya.")
     Exit
EndFunc

 

Link to comment
Share on other sites

  • Moderators

There is a section on the Wiki with some guidelines and Best Practices. Have you read it?

UDF-spec - AutoIt Wiki (autoitscript.com)

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

  • 3 weeks later...

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...