Jump to content

Embedding Lua scripts in AutoIt


JRowe
 Share

Recommended Posts

Lua is a programming language much like AutoIt. It has similar, simple, procedural syntax, and is built for small size and speed. It is extremely customizable, allows tight integration with c code, and vice versa, which is what makes it easy to use with AutoIt - all au3 code needs is a few dllCalls to set up the Lua "state", and functions to get/set data within the Lua context.

Features: http://www.lua.org/about.html

Lua is very fast, and allows us to extend AutoIt easily, similar to the way plugins work. This also allows us to immediately and easily utilize every package for Lua that currently runs on Windows - game engines, GUI libraries, networking, number crunching, and more.

I think the biggest benefit comes from the ability to create a framework application in AutoIt, and then offload CPU intensive functions, or functions intended to be customized (plugins) to Lua.

LuaForWindows comes with a ton of extra Lua libraries meant to enhance usability on Windows. You'll find that while AutoIt has easily as much utility, LFW has a few notable packages that will make many of us very happy:

LuaCURL (internet), LuaExpat(xml), LuaSQL(database), WxLua(GUI), LuaGL(low level 3D), Lanes(sane multithreading), LOOP(object oriented implementation.)

Here's an example of how to get a simple Lua function working in an AutoIt script - you pass parameters, and return results in the way you'd expect. Lua uses a stack concept to facilitate data passing back and forth between the host (AutoIt) and the script (Lua.)

The messy bits should be bundled into helper functions that make it easier to integrate any old functions, but this should be plenty to get us started. 3 cheers for Smoke_N!

;Author: Smoke_N
Opt("MustDeclareVars", 1)

#region Main Globals
Global $__g_sluadll = "lua51.dll"
Global $__g_hluadll = 0
Global $__g_pluanewstate = 0

Global Const $LUA_VERSION = "Lua 5.1"
Global Const $LUA_RELEASE = "Lua 5.1.1"
Global Const $LUA_VERSION_NUM = 501
Global Const $LUA_COPYRIGHT = "Copyright (C) 1994-2006 Lua.org, PUC-Rio"
Global Const $LUA_AUTHORS = "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
Global Const $LUA_SIGNATURE = "Lua"
Global Const $LUA_MULTRET = (-1)
Global Const $LUA_REGISTRYINDEX = (-10000)
Global Const $LUA_ENVIRONINDEX = (-10001)
Global Const $LUA_GLOBALSINDEX = (-10002)
Global Const $LUA_YIELD_ = 1
Global Const $LUA_ERRRUN = 2
Global Const $LUA_ERRSYNTAX = 3
Global Const $LUA_ERRMEM = 4
Global Const $LUA_ERRERR = 5
#endregion Main Globals

#region Test Code
If Not _Lua_Initiate() Then Exit 1

_Lua_Open()
_Lua_OpenLibs()

_Lua_DoFile("add.lua")
_Lua_GetGlobal("add")
_Lua_PushNumber(41)
_Lua_PushNumber(22)
ConsoleWrite("Making the call..." & @CRLF)

_Lua_Call(2, 1)
ConsoleWrite("Call made" & @CRLF)

Global $n_sum = _Lua_ToNumber(-1)
ConsoleWrite("done." & @CRLF)

_Lua_Pop(1)
ConsoleWrite("done.." & @CRLF)

_Lua_Close()
_Lua_DeInitiate()

ConsoleWrite($n_sum & @CRLF)
#endregion Test Code

#region Functions
Func _Lua_Open()

    $__g_pluanewstate = 0

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    Local $a_ret = DllCall($__g_hluadll, "ptr:cdecl", "luaL_newstate", "ptr", 0, "ptr", 0)
    If @error Or $a_ret[0] = 0 Then Return SetError(1, 0, 0)

    $__g_pluanewstate = $a_ret[0]

    Return $a_ret[0]
EndFunc

Func _Lua_Close($p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "luaL_close", "ptr", $p_state)
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_OpenLibs($p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "luaL_openlibs", "ptr", $p_state)
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_LoadFile($s_filename, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    Local $a_ret = DllCall($__g_hluadll, "int:cdecl", "luaL_loadfile", "ptr", $p_state, "str", $s_filename)
    If @error Or $a_ret[0] <> 0 Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_DoFile($s_filename, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    Local $i_load = _Lua_LoadFile($s_filename)
    Local $i_pcall = _Lua_PCall(0, $LUA_MULTRET, 0)

    If BitOR($i_load, $i_pcall) = 0 Then Return SetError(1, 0, 0)

    ;Local $a_ret = DllCall($__g_hluadll, "int:cdecl", "luaL_dofile", "ptr", $p_state, "str", $s_filename)

    Return 1
EndFunc

Func _Lua_GetGlobal($s_name, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    ;DllCall($__g_hluadll, "none:cdecl", "lua_getglobal", "ptr", $p_state, "str", $s_name)
    _Lua_GetField($s_name, $LUA_GLOBALSINDEX, $p_state)
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_GetField($s_char, $i_index = $LUA_GLOBALSINDEX, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_getfield", "ptr", $p_state, "int", Int($i_index), "str", $s_char)
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_PCall($i_args, $i_results, $i_errfunc = 0, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    Local $a_ret = DllCall($__g_hluadll, "int:cdecl", "lua_pcall", _
        "ptr", $p_state, "int", Int($i_args), "int", Int($i_results), "int", Int($i_errfunc))
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_PushInteger($i_num, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_pushinteger", "ptr", $p_state, "int", Int($i_num))
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_PushNumber($n_num, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_pushnumber", "ptr", $p_state, "double", Number($n_num))
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_PushString($s_str, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_pushstring", "ptr", $p_state, "str", $s_str)
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_Call($i_args, $i_results, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_call", "ptr", $p_state, "int", Int($i_args), "int", Int($i_results))
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_ToNumber($i_index, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    Local $a_ret = DllCall($__g_hluadll, "double:cdecl", "lua_tonumber", "ptr", $p_state, "int", Int($i_index))
    If @error Then Return SetError(1, 0, 0)

    Return $a_ret[0]
EndFunc

Func _Lua_Pop($i_pop, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    DllCall($__g_hluadll, "none:cdecl", "lua_pop", "ptr", $p_state, "int", Int($i_pop))
    If @error Then Return SetError(1, 0, 0)

    Return 1
EndFunc

Func _Lua_Initiate()
    If $__g_hluadll <> 0 Then Return 1

    $__g_hluadll = DllOpen($__g_sluadll)
    If $__g_hluadll = -1 Then
        $__g_hluadll = 0
        Return SetError(-1, 0, 0)
    EndIf

    Return 1
EndFunc

Func _Lua_DeInitiate()
    If $__g_hluadll = 0 Then Return 1

    DllClose($__g_hluadll)

    $__g_hluadll = 0

    Return 1

EndFunc
#endregion Functions

Here's a sample Lua script. Put this in a file called "add.lua"

function add (x, y)
    print("hello world")
    --print() is just like consoleWrite. After print, we need to call io.flush() to immediately output the results of the previous print
    io.flush()
    return (x + y)
end

LuaAu.zip This contains all the files needed to embed a Lua script. Including other libraries and resources requires a bit of Lua knowledge. I recommend using what's known as the blue PiL, or Programming in Lua. It's available to read online at: http://www.lua.org/pil/

If it doesn't work immediately, you may need the vcredist here: http://luaforwindows.googlecode.com/files/vcredist_x86.exe

Link to comment
Share on other sites

This is exciting! Thanks JRowe! 5* Posted Image

Link to comment
Share on other sites

  • 2 weeks later...

Created func for boolean.

Func _Lua_ToBoolean($i_index, $p_state = 0)

    If Not _Lua_Initiate() Then Return SetError(-1, 0, 0)

    If $p_state = 0 Then $p_state = $__g_pluanewstate

    Local $a_ret = DllCall($__g_hluadll, "int:cdecl", "lua_toboolean", "ptr", $p_state, "int", Int($i_index))
    If @error Then Return SetError(1, 0, 0)

    Return $a_ret[0]
EndFunc
Edited by E1M1

edited

Link to comment
Share on other sites

  • 2 weeks later...
Link to comment
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
 Share

  • Recently Browsing   0 members

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