Page 2 of 5 FirstFirst 1234 ... LastLast
Results 11 to 20 of 42

Thread: Getting started with LUA/pas2lua

  1. #11

    Getting started with LUA/pas2lua

    That's what I was going to use, but in FPC it is in the DOS unit ... so I wasn't sure. I might as well try it I guess.

    Edit: I'm thinking of, in that loop, using a "callback" to the script to as a function to add a string to the record. How would I code the pascal part to accept the parameter of an "inline" function, and then call that function with a single variable during that loop? I'd call the function sorta like this:
    Code:
    system.find("library/*.lua",function(file) table.insert(library_files,file) end)

  2. #12

    Getting started with LUA/pas2lua

    Well, actually, you don't include the DOS library directly. You include the SysUtils lib directly. Then depending on platform it will include the right implementation of findfirst/next. This way it works on Mac, Unix, Linux, Windows, etc...

    On your question, can you give me a full blown example. I'm a bit lost as to what your wanting, and the one liner didn't do it for me . High level will work:

    FindFirst()
    CallScript(MyFunction)
    FindNext()
    ReturnToCallScript()

    Then what you want the script to do and what your global records/objects/variables should be.

  3. #13

    Getting started with LUA/pas2lua

    I just looked in the RTL document and you're 100% right. Silly me. :roll:

    I do that so often I sometimes want to beat my head against the table. Anyhow.

    I can't really give a full blown example at the moment because I haven't written anything; I need a function that finds all scripts in the library directory and gives that to my main script. So there's one of two methods: passing back a table, or calling a handler function. I'm not entirely certain how to do either. What I would do is register a global variable, we'll just call it library, with a sub-table named scripts.

    IE:
    Code:
     -- Main.lua
    
    library = {
      scripts = {},
    }
    So I would do something like register this function (forgive me, I'm really crawling in the dark on how to make a table in Lua) with Lua:[pascal]procedure system_search(L : PLua_State);
    var
    searchResult : TSearchRec;
    mask: string;
    results: longint;
    begin
    mask := lua_tostring(L,1);
    if FindFirst(mask, faAnyFile, searchResult) = 0 then
    begin
    repeat
    // lua_pushstring(L,searchResult.Name); ?
    inc(results);
    until FindNext(searchResult) <> 0;

    // Must free up resources used by these successful finds
    FindClose(searchResult);
    end;
    lua_settable(L,-results); // ?
    end;[/pascal]

    Then I'd call it in the script sort of like this:
    Code:
    library.scripts = system.find&#40;"library/*.lua"&#41;
    And it would return something about like this:
    Code:
    &#123;
      "hello.lua",
      "recursive_search.lua",
    &#125;
    And so on.

    Like I said, I'm really lost on how to mess with functions and passing back and forth parameters and results. Not to mention just how to go about designing a function like that, since I've never worked with a stack before.

  4. #14

    Getting started with LUA/pas2lua

    Gotcha! Ok, try this:[pascal]function lua_Search(L : PLua_State) : integer; cdecl;
    var
    i, n, idx : integer;
    searchResult : TSearchRec;
    path, mask: AnsiString; // You should always use AnsiStrings and not Strings
    begin
    n := lua_gettop(L); // Get the number of items being passed in
    if n > 0 then
    begin
    path := luatostring(L, 1);
    if n > 1 then
    mask := luatostring(L, 2)
    else
    mask := '*.*';
    end
    else
    begin
    mask := '*.*';
    path := ExtractFilePath(ParamStr(0));
    end;
    lua_newtable(L); // Create a new table
    idx := lua_tointeger(L, 1);
    lua_Search := 1;
    i := 1;
    if FindFirst(path + mask, faAnyFile, searchResult) = 0 then
    begin
    repeat
    lua_pushinteger(L, i);
    inc(i);
    luapushstring(path + mask);
    lua_settable(L, idx);
    until FindNext(searchResult) <> 0;
    FindClose(searchResult);
    end;
    end;[/pascal]

    Later (if your using my TLua object) register the function with:[pascal]Lua.RegisterMethod('FindFiles', @lua_Search)[/pascal]
    If you are using pure Lua, then registering the function becomes:[pascal]luapushstring(L, 'FindFiles');
    lua_pushcfunction(L, @lua_Search);
    lua_settable(L, LUA_GLOBALSINDEX);[/pascal]

    Then for a lua script:
    Code:
    results = FindFiles&#40;SomePath, '*.bmp'&#41;
    if results~= nil then
      for k, v in pairs&#40;results&#41; do
        print&#40;v&#41;
      end
    end
    On a side note; really you should allow for a recursive flag, allow path and filename to be passed in a new table instead of all in one, and other options. By default, FindFirst/FindNext are not recursive, and you would have to write handlers to manage this. Unfortunately (for you) I never completed the code I was working on for a good cross platform lua_FindFiles implementation, if I do, I'll post it up

  5. #15

    Getting started with LUA/pas2lua

    Thank you very much Jeremy, I'll try that in a little bit. I know how to make things recursive, but it will take some additional helper functions and all. I'll make a testbed for that later. But it isn't too hard to do.

    I just was lost on how to pass stuff to Lua. So I'll write up a cross platform, recursive, findfiles function soon enough and then share it with you.

  6. #16

    Getting started with LUA/pas2lua

    Uh, Jeremy? I just tried compiling a sandbox, and it gave me about 48 errors in FPC 2.0.4 saying that "result is undefined". Did I leave something out?

    luaexec.pas:
    Code:
    program luaexec;
    
    &#123;$MODE DELPHI&#125;
    
    uses LuaWrapper, lua, LuaUtils, SysUtils, crt;
    
    function lua_Search&#40;L &#58; PLua_State&#41; &#58; integer; cdecl;
    var
      i, n, idx &#58; integer;
      searchResult &#58; TSearchRec;
      path, mask&#58; AnsiString; // You should always use AnsiStrings and not Strings
    begin
      n &#58;= lua_gettop&#40;L&#41;; // Get the number of items being passed in
      if n > 0 then
        begin
          path &#58;= luatostring&#40;L, 1&#41;;
          if n > 1 then
            mask &#58;= luatostring&#40;L, 2&#41;
          else
            mask &#58;= '*.*';
        end
      else
        begin
          mask &#58;= '*.*';
          path &#58;= ExtractFilePath&#40;ParamStr&#40;0&#41;&#41;;
        end;
      lua_newtable&#40;L&#41;;  // Create a new table
      idx &#58;= lua_tointeger&#40;L, 1&#41;;
      lua_Search &#58;= 1;
      i &#58;= 1;
      if FindFirst&#40;path + mask, faAnyFile, searchResult&#41; = 0 then
        begin
          repeat
            lua_pushinteger&#40;L, i&#41;;
            inc&#40;i&#41;;
            luapushstring&#40;path + mask&#41;;
            lua_settable&#40;L, idx&#41;;
          until FindNext&#40;searchResult&#41; <> 0;
          FindClose&#40;searchResult&#41;;
        end;
    end;
    
    function lua_KeyPressed&#40;L &#58; PLua_State&#41; &#58; integer; cdecl;
    begin
      luapushboolean&#40;L,KeyPressed&#41;;
    end;
    
    var main&#58; TLua;
    
    BEGIN
      main &#58;= TLua.Create&#40;nil&#41;;
      main.LoadFile&#40;'main.lua'&#41;;
      main.RegisterMethod&#40;'FindFiles', @lua_Search&#41;;
      main.RegisterMethod&#40;'KeyPressed', @lua_KeyPressed&#41;;
      main.Execute;
      main.free;
    END.
    main.lua:
    Code:
     -- MAIN.LUA
     
    print&#40;"Greetings Terran!"&#41;;
    while not KeyPressed&#40;&#41; do end
    Should work according to what I know. FPC has always seemed picky to me though, so I never quite understood the problem with things like this. I thought result was always assumed in a function.

    Errors raised:
    Code:
    lua.pas&#40;796,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;814,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;840,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;845,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;850,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;855,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;860,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;865,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;870,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;875,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;880,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;900,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;905,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;915,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;934,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;946,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;948,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;953,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;958,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;963,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;968,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;973,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;978,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;983,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;988,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;989,6&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;990,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;995,3&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;996,6&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;997,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;1026,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;1030,5&#41; Error&#58; Identifier not found "result"
    lua.pas&#40;1073&#41; Fatal&#58; There were 32 errors compiling module, stopping
    lua.pas&#40;5,46&#41; Fatal&#58; Compilation aborted

  7. #17

    Getting started with LUA/pas2lua

    Robert, good first try. There are a few things in the lua.pas file that arn't quite right. Apparently I haven't updated the lua.pas that is on the website in a while (my apologies).

    Try downloading: http://www.eonclash.com/LUA/luaexec.zip

    It is an updated version of what you posted that runs just fine . You will want to use the units (lua, luawrapper, luautils, cutils, and luaobject) from this zip file for your projects. Basically part of the problem was that in FPC result doesn't exist, you have to use function name:[pascal]// This won't work in fpc
    function Test():Integer;
    begin
    result := 1;
    end;
    // This is the "proper" way to do it
    function Test():Integer;
    begin
    Test := 1;
    end;[/pascal]

    Also, in your lua_KeyPressed method you never set the method result. So I added it in for you . Now everything should work fine.

    I also had a problem in the code I gave you. I did a create table and then a tointeger, that tointeger should have been a gettop

    Finally, a minor fix in the push to accommodate searchResult.Name instead of path + mask makes it all work hunky dory.

  8. #18

    Getting started with LUA/pas2lua

    Oh, I understand. I think that's a little silly though that they didn't reuse result like Delphi does as a standard feature. It would help when someone starts out with the compiler.

    Thanks for updating the headers again.

    Is there a specific reason for the cdecl; tagged onto the functions? I'm not entirely sure what it does, though I suspect it makes things easier in interfacing with a DLL. And the result variable of a function is the number of parameters returned, right? I think I'm starting to get a hang of this.

    Now to start implementing the better aspects of FPC's console functions and making something better out of it. Like, columns displaying library scripts, window functionality, and some basic readkey stuff to tie all that into an easy executable for my scripts. Then there's no need to touch the app for a while, as I change things around and mess with stuff. I might end up writing a batch image converter to take screenshots from a given directory, convert them to jpeg/png and then dump them into another directory.

    Thanks much for your help thus far! Maybe once I get a hang of this stuff and have a little more time I can help you out with your game engine. That would be kinda fun I think, but I honestly don't know enough right now on top of lacking the time to do more than fiddle around. But hey, getting acquainted with the language and its usage is half the battle.

    (As a side note, I might have a use for this knowledge in my work. Our web server stuff is just about inbetween a rock and a hard place, and Lua just might be able to get us out. Assuming I can talk my coworkers into it. Keep your fingers crossed!)

  9. #19

    Getting started with LUA/pas2lua

    I'll quick run this by you to see if I understand it right, but I think I do. I'm writing a simplistic library for pascal/lua to handle the CRT functionality of Freepascal. So I've written a function supporting multiple types, integer and string, and use that to set the text color of the console. (IE, the foreground color)

    [pascal]function lua_TextColor(L: PLua_State) : integer; cdecl;
    var n,i: integer;
    c: byte;
    s: string;
    const colors: array[0..15] of string = ('black','blue','green','cyan','red','magenta','br own','lightgray','darkgray',
    'lightblue','lightgreen','lightcyan','lightred','l ightmagenta','yellow','white');
    begin
    n := lua_gettop(L);
    assert(n = 1, 'Number of arguments to TextColor must be 1.');
    lua_TextColor := 0;

    if lua_isstring(L,1) then begin
    s := lua_tostring(L,1);
    c := 15; // The default color.
    for i := 0 to 15 do
    if lowercase(s) == colors[i] then begin
    c := i;
    break;
    end;
    end else if lua_isnumber(L,1) then
    c := byte(min(lua_tointeger(L,1),15));
    else assert(false,'Error, invalid type passed to TextColor!');

    assert((c >= 0)and(c < 16), 'TextColor must be called with a value equal to, or between 0 and 15.');
    TextColor(c);
    end;[/pascal]

    So eventually I want to register a library, not just a function. Referencing this page I think I know how to do it, save one thing. Must I include the ending (nil,nil) entry? And how do I define a constant 2D array in FreePascal? I never was good at constant multidepth arrays. :roll: Like this?
    Code:
    const crtlib&#58; array of array of variant = &#40;&#40;"KeyPressed", @lua_KeyPressed&#41;, &#40;"TextColor", @lua_TextColor&#41;, &#40;nil,nil&#41;&#41;;
    Or, is this impossible with FPC? Seems like a messy array of variants to me. :? Can I actually do this in pascal, or not? I'm guessing that, as a long shot, I could register it the normal way as "crt.TextColor" rather than just "TextColor".

  10. #20

    Getting started with LUA/pas2lua

    Well, cdecl tells the compiler to place the items in C fashion for the methods (functions/procedures). Since Lua is developed in C it expects the method params and return values in C style and not pascal style (more on this all over the web if you want to research it).

    Yes, the result of the function is the number of variables that YOU placed onto the stack (or returned). If you have variables in a table then you only count the table .

    On the topic of Result, this is something that Borland introduced into the pascal language. The pascal standard states that you should use the method name and not a generic handler . So actually, its Borland Delphi thats wrong .

    Finally, hate to burst your bubble, but I am very selective of the people I let work on the game engine. In fact, right now there is only one other person that ever looks at the code, and he doesn't modify it . On most of my projects I don't mind, but this one is close to the heart and has paying customers, so I keep a very tight lid on the source. Though, if you ever decide to do one of your own, feel free to ask questions, as I think I've managed to screw up about everything that could be screwed up .

Page 2 of 5 FirstFirst 1234 ... LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •