Alien und VCLua für SciTE

  • Für LUA gibt es einige praktische Erweiterungen als DLL, die jedoch nicht mit der in SciTE integrierten Version funktionieren.
    SciTE verwendet LUA 5.1 und exportiert die nötigen Funktionen auch in der SciTE.exe. Die DLLs erwarten dagegen die Exports durch eine DLL namens lua5.1.dll.
    Die hier angebotenen DLLs habe ich so modifiziert, dass sie nun nach SciTE.exe statt lua5.1.dll suchen und daher problemlos in SciTE-LUA funktionieren.

    Alien bietet eine Schnittstelle zum Aufruf von Funktionen in DLLs, wodurch die komplette Windows API zur Verwendung offen steht.
    VCLua ist eine GUI-Bibliothek für LUA. Für die Verwendung mit SciTE scheint mir aber doch die von SciTE-ru erstellte GUI-Bibliothek besser geeignet sein.

    Download und Dokumentation für die SciTE-ru GUI befinden sich hier:
    http://scite-ru.googlecode.com/svn/trunk/pack…/LuaLib/gui.dll
    http://scite-ru.googlecode.com/svn/trunk/lualib/gui/docs/gui.html
    Weiterhin gibt es bei SciTE-ru auch die Shell.dll (Doku) und lpeg (Doku) (dazu re, eine auf lpeg basierende Regex-Bibliothek)

    Der Anhang enthält die gepatchten DLLs und die nötigen lua-Dateien.

    Ein Beispiel für alien:

    Spoiler anzeigen
    [autoit]

    -- timetype: 1 - created, 2 - accessed, 3 - modified
    local function FileGetTime(filepath, timetype)
    timetype = timetype or 1
    local alien = require "alien"

    [/autoit] [autoit][/autoit] [autoit]

    local GENERIC_READ = 0x80000000
    local GENERIC_WRITE = 0x40000000
    local OPEN_EXISTING = 3

    [/autoit] [autoit][/autoit] [autoit]

    local FILETIME = alien.defstruct {
    { 'dwLowDateTime' , 'ulong'},
    { 'dwHighDateTime' , 'ulong'}
    }

    [/autoit] [autoit][/autoit] [autoit]

    local CreateFile = assert(alien.kernel32.CreateFileA)
    CreateFile:types{ret = "pointer", abi = 'stdcall', "string",
    "int", "int", "pointer", "int", "int", "pointer"}
    local CloseHandle = assert(alien.kernel32.CloseHandle)
    CloseHandle:types{ret = 'int', abi = 'stdcall', "pointer"}
    local GetFileTime = assert(alien.kernel32.GetFileTime)
    GetFileTime:types{ret = 'int', abi = 'stdcall', "pointer", "pointer", "pointer", "pointer"}

    [/autoit] [autoit][/autoit] [autoit]

    local hFile = CreateFile(filepath, GENERIC_READ, 7, nil, OPEN_EXISTING, 0 ,nil)

    [/autoit] [autoit][/autoit] [autoit]

    -- check for success
    local tmp = alien.buffer(4)
    tmp:set(1, hFile, 'pointer')
    local hnum = tmp:get(1, 'int')
    if hnum == -1 then return nil end

    [/autoit] [autoit][/autoit] [autoit]

    local fT = FILETIME:new()
    local success
    if timetype == 1 then success = GetFileTime(hFile, fT(), nil, nil)
    elseif timetype == 2 then success = GetFileTime(hFile, nil, fT(), nil)
    else then success = GetFileTime(hFile, nil, nil, fT())

    [/autoit] [autoit][/autoit] [autoit]

    CloseHandle(hFile)

    [/autoit] [autoit][/autoit] [autoit]

    if not success then return nil end

    [/autoit] [autoit][/autoit] [autoit]

    local get_unix = alien.Ntdll.RtlTimeToSecondsSince1970
    get_unix:types{ret = 'int', abi = 'stdcall', "pointer", "ref uint"}
    success, timeval = get_unix(fT(), 0)
    if not success then return nil end

    [/autoit] [autoit][/autoit] [autoit]

    return timeval
    end

    [/autoit] [autoit][/autoit] [autoit]

    --===================================================--
    -------------------|> EXAMPLE <|---------------------
    --===================================================--

    [/autoit] [autoit][/autoit] [autoit]

    local unix = FileGetTime("C:\\windows\\explorer.exe", 3)
    trace (unix .. "\n")

    [/autoit]

    Installation:
    - Archiv in das SciTE-Verzeichnis entpacken
    * Folgende Zeile an den Anfang von SciTE/LUA/SciTEStartup.lua setzen:

    Code
    package.cpath = props["SciteDefaultHome"].."\\LuaLib\\?.dll;"..package.cpath
    • Offizieller Beitrag

    Danke progandy :thumbup:
    Nun kann man auch etwas anspruchsvollere Lua-Bibliotheken im Standard-SciTE nutzen. Ich hatte bisher in der lua.properties auf meine externe Lua-Installation verlinkt, was aber nur auf meinem Rechner sinnvoll ist.
    Na dann schaun wir mal, was sich da noch für interessante Symbiosen ergeben.

    • Offizieller Beitrag

    Als erstes noch ein Hinweis zur Installation:
    In der SciTEStartup.lua ist noch der Eintrag:
    LoadLuaFile("alien.lua")
    erforderlich.

    Ich habe jetzt mal ein wenig damit gespielt, komme aber nicht zum Erfolg.
    Hier ein Bsp.


  • Du musst den Pointer der Struct übergeben: GetCursorPos(pos())
    Anschließend ist die DLLStruct befüllt und du kannst per pos.X bzw. pos.Y auf die Werte zugreifen.
    PS: Auf alien.luaforge.net findest du im Abschnitt Structs ein kleines Beispiel für tagRECT.

    Zitat

    LoadLuaFile("alien.lua")


    Das war bei mir nicht nötig. Das wurde von require erledigt.

    Spoiler anzeigen
    [autoit]

    local alien = require "alien"

    [/autoit] [autoit][/autoit] [autoit]

    -- Struktur erstellen
    local POINTAPI = alien.defstruct {
    { 'X', 'int'},
    { 'Y', 'int'}
    }

    [/autoit] [autoit][/autoit] [autoit]

    -- Dll-Aufruf erstellen
    local GetCursorPos = assert(alien.user32.GetCursorPos)
    GetCursorPos:types{ret = 'int', abi = 'stdcall', "pointer"}

    [/autoit] [autoit][/autoit] [autoit]

    --~ Zuerst habe ich versucht, ähnlich wie in deinem Bsp., die Funktion "new" anzuwenden.
    local pos = POINTAPI:new() -- ergibt aber nur ein leeres Table?

    [/autoit] [autoit][/autoit] [autoit]

    --~ Das habe ich dann als Parameter für die Funktion verwendet.
    local ret = GetCursorPos(pos())
    print('Erfolg: '..pos.X..'-'..pos.Y) -- Return ist = "0" --> also kein Erfolg

    [/autoit] [autoit][/autoit] [autoit]

    --~ Falls der Aufruf erfolgreich ist (und was muß ich dazu tun) - wie komme ich dann an die Daten?
    --~ Ist dafür die Funktion "byval" zuständig? Mit welchen Parametern muß ich sie dann aufrufen

    [/autoit]

    2 Mal editiert, zuletzt von progandy (7. Mai 2012 um 13:11)

    • Offizieller Beitrag

    Danke, damit komme ich schonmal weiter.

    Ich habe jetzt angefangen mir eine API-Bibliothek für Lua zu erstellen.
    Aber folgende Funktion bleibt erfolglos. Siehst du einen Fehler? Ich habe zwei Varianten probiert:

    und:

  • nLength von SECURITY_ATTRIBUTES musst du auf SECURITY_ATTRIBUTES.size setzen.

    • Offizieller Beitrag

    Ich habe heute erstmals versucht die gui.dll anzuwenden. Aber das ist leider eine Nullnummer. Die Dokumentation enthält ebenso, wie die Examples, Funktionen, die in der dll gar nicht existieren.

    Wenn man die gui.dll einbindet werden folgende Funktionen nach SciTE exportiert:

    gui.dll - Export
    Inhalt lt. Doku - aber nicht exportiert

    Und gerade bei diesen fehlenden Punkten sind die Grafik-Objekte.
    Die gui.dll ist somit leider nicht einsetzbar.

    EDIT 19.01.2014
    Ich muss mich korrigieren - die Dll ist einsetzbar. Allerdings ist sie (aus meiner Sicht) mit einem Syntax-Fehler behaftet, aus dem meine Verwirrung resultierte.
    Bibliotheken lassen sich in Lua wie folgt einbinden:

    Code
    -- Variante 1:
    Variable = require "Modul"
    -- Elemente des Moduls lassen sich mit "Variable.Element/Methode" ansprechen
    
    
    -- Variante 2:
    require "Modul"
    -- Elemente des Moduls lassen sich mit "Modul.Element/Methode" ansprechen


    Die gui.dll ermöglicht den Zugriff auf die Elemente nur mit Variante 2, wohingegen die Methoden auch mit Variante 1 exportiert werden. Da wurde wohl in der Dll geschlampt und vergessen die Objekte zu exportieren. Wenn man weiß, dass dem so ist, ist es ja nicht dramatisch. Aber diese Tatsache ist in der (sowieso unterirdisch mangelhaften) Doku nicht erwähnt.
    Im Allgemeinen ist es empfehlenswert, Module mit Variante 1 zu laden, um diese in den Lokalen Space importieren zu können. Mit Variante 2 bin ich gezwungen immer den Globalen Space zu nutzen - und das ist eine Performancebremse. Lua hat die beste Performance im Lokalen Space.