Integrating Lua

Creating, porting and using libraries with Ultibo
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Integrating Lua

Postby msx80 » Thu Sep 13, 2018 9:10 pm

Update: here's the working library: https://github.com/msx80/Lua4Ultibo/

Hi, i'm trying to integrate Lua. Seems like it should work with no problem but i have some strange linking error. I tried different version of the GCC toolchain as it seems that newest one will give even more errors. I'm using gcc-arm-none-eabi-4_8-2014q3, which should match the one used by fpc (correct me if i'm wrong).
First i downloaded lua sources and compile them with the following commands (adapted from the makefile):

Code: Select all

arm-none-eabi-gcc -mabi=aapcs -march=armv6 -marm -mfpu=vfp -mfloat-abi=hard -D__DYNAMIC_REENT__ -DLUA_32BITS -O2 -c *.c
arm-none-eabi-ar rcs liblua.a lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o


Now i have a liblua.a. I copied into the project folder, then wrote the following simple "header file" (ctypes is not really needed but i was trying everything).

Code: Select all

unit LUAUnit;

{$linklib lua}
{$mode objfpc}{$H+}

interface

uses
  Syscalls,ctypes;

const
LUA_OK : Integer = 0;
LUA_MULTRET: Integer = -1;

type Plua_State = pointer;

function luaL_newstate(): Plua_State; cdecl; external 'lua' name 'luaL_newstate';
procedure luaL_openlibs(luaState: Plua_State); cdecl; external 'lua' name 'luaL_openlibs';
function luaL_loadfile(luaState: Plua_State; filename: PChar): Integer; cdecl; external 'lua' name 'luaL_loadfile';
function lua_pcall(luaState: Plua_State; nargs, nresults, errfunc: Integer): Integer; cdecl; external 'lua' name 'lua_pcall';
procedure lua_call(luaState: Plua_State; nargs:cint32;  nresults: cint32); cdecl; external 'lua' name 'lua_call';
function luaL_loadstring(luaState: Plua_State; s: PChar): Integer; cdecl; external 'lua' name 'luaL_loadstring';

implementation

end.


It's just a start to see if i can execute any Lua code at all. This is the test procedure:

Code: Select all

procedure runLua;
var luas:Plua_State;
    res:integer;
begin

  luas := luaL_newstate();
  ConsoleWindowWriteLn(WindowHandle,'LUA handle is: '+inttostr(qword(luas)));
  luaL_openlibs(luas);

  res:=luaL_loadstring(luas, 'print("hello from lua");print(_VERSION)');
  if  res <> LUA_OK then  raise exception.create('NOT loaded');
  ConsoleWindowWriteLn(WindowHandle,'Loaded : '+IntToStr(res));

  //lua_pcall(luas, 0, LUA_MULTRET,0);
  if  res <> LUA_OK then  raise exception.create('NOT executed');
end;         


Now as it is, it works. I can see that luaL_newstate returns a valid pointer and luaL_loadstring returns LUA_OK (0). The problem is, if i uncomment the lua_pcall line to actually execute the code, the program will break at linking with the following errors:

Code: Select all

Free Pascal Compiler version 3.1.1 [2017/09/18] for arm
Copyright (c) 1993-2015 by Florian Klaempfl and others
(1002) Target OS: Ultibo
(3104) Compiling HelloGLES.lpr
C:\my\path\GlesRPz\HelloGLES.lpr(46,64) Warning: (4056) Conversion between ordinals and pointers is not portable
C:\my\path\GlesRPz\HelloGLES.lpr(24,1) Hint: (5023) Unit "RaspberryPi" not used in HelloGLES
(9009) Assembling hellogles
(9015) Linking HelloGLES
C:\my\path\GlesRPz\lib\arm-ultibo\HelloGLES.o: In function `P$HELLOGLES_$$_RUNLUA':
HelloGLES.lpr:(.text.n_p$hellogles_$$_runlua+0x110): undefined reference to `lua_pcall'
C:\my\path\GlesRPz\HelloGLES.lpr(93,58) Error: (9013) Error while linking
C:\my\path\GlesRPz\HelloGLES.lpr(93,58) Fatal: (10026) There were 1 errors compiling module, stopping
Fatal: (1018) Compilation aborted
Error: C:\Ultibo\Core\fpc\3.1.1\bin\i386-win32\ppcrossarm.exe returned an error exitcode


It's very strange that it can't see lua_pcall, but can see the other two functions. Doing some tests, i see that some functions are ok, while others no. luaL_loadfile is another that can't be found.

But I'm sure all of them are inside my liblua.a (you can find it here)

Any idea of what could be going on? Why some functions are visible and others aren't?

Thanks :)
Last edited by msx80 on Mon Oct 01, 2018 8:44 am, edited 1 time in total.
User avatar
Ultibo
Site Admin
Posts: 2040
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: Integrating Lua

Postby Ultibo » Thu Sep 13, 2018 11:58 pm

Hi,

We've actually already had a go at building lua and it builds successfully but we haven't released what we have done because it hasn't been tested.

In order to build it we created a set of modified makefiles, the one for ARM6 (Pi A/B/Zero) looks like this:

Code: Select all

# makefile for building Lua
# see INSTALL for installation instructions
# see ../Makefile and luaconf.h for further customization

# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================

# Warnings valid for both C and C++
CWARNSCPP= \
   # -pedantic \  /* warns if we use jump tables */
   -Wextra \
   -Wshadow \
   -Wsign-compare \
   -Wundef \
   -Wwrite-strings \
   -Wredundant-decls \
   -Wdisabled-optimization \
   -Wdouble-promotion \
    -Wstrict-aliasing=3   # not accepted by clang \
    -Wno-aggressive-loop-optimizations   # not accepted by clang \
    -Wlogical-op   # not accepted by clang \
   # the next warnings generate too much noise, so they are disabled
   # -Wconversion  -Wno-sign-conversion \
   # -Wsign-conversion \
   # -Wstrict-overflow=2 \
   # -Wformat=2 \
   # -Wcast-qual \

# The next warnings are neither valid nor needed for C++
CWARNSC= -Wdeclaration-after-statement \
   -Wmissing-prototypes \
   -Wnested-externs \
   -Wstrict-prototypes \
   -Wc++-compat \
   -Wold-style-definition \


CWARNS= $(CWARNSCPP) $(CWARNSC)


# -DEXTERNMEMCHECK -DHARDSTACKTESTS -DHARDMEMTESTS -DTRACEMEM='"tempmem"'
# -g -DLUA_USER_H='"ltests.h"'
# -pg -malign-double
# -DLUA_USE_CTYPE -DLUA_USE_APICHECK
# (in clang, '-ftrapv' for runtime checks of integer overflows)
# -fsanitize=undefined -ftrapv -fno-inline
TESTS= -DLUA_USER_H='"ltests.h"' -O0

# -mtune=native -fomit-frame-pointer
# -fno-stack-protector
# -DLUA_NILINTABLE
LOCAL = $(TESTS) $(CWARNS) -g -DEXTERNMEMCHECK



# enable Ultibo
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_ULTIBO --specs=nosys.specs -O2 -mabi=aapcs -marm -march=armv6 -mfpu=vfp -mfloat-abi=hard -D__DYNAMIC_REENT__
MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS=


CC= arm-none-eabi-gcc
CFLAGS= -Wall -O2 $(MYCFLAGS) -Wfatal-errors
AR= arm-none-eabi-ar rcu
RANLIB= arm-none-eabi-ranlib
RM= rm -f



# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========


LIBS = -lm

CORE_T=   liblua.a
CORE_O=   lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
   lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
   ltm.o lundump.o lvm.o lzio.o ltests.o
AUX_O=   lauxlib.o
LIB_O=   lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \
   lutf8lib.o loadlib.o lcorolib.o linit.o

# LUA_T=   lua
LUA_O=   lua.o

# LUAC_T=   luac
# LUAC_O=   luac.o print.o

ALL_T= $(CORE_T) $(LUA_T) $(LUAC_T)
ALL_O= $(CORE_O) $(LUA_O) $(LUAC_O) $(AUX_O) $(LIB_O)
ALL_A= $(CORE_T)

all:   $(ALL_T)

o:   $(ALL_O)

a:   $(ALL_A)

$(CORE_T): $(CORE_O) $(AUX_O) $(LIB_O) $(LUA_O)
   $(AR) $@ $?
   $(RANLIB) $@

$(LUA_T): $(LUA_O) $(CORE_T)
   $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(CORE_T) $(LIBS) $(MYLIBS) $(DL)

$(LUAC_T): $(LUAC_O) $(CORE_T)
   $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(CORE_T) $(LIBS) $(MYLIBS)

clean:
   #rcsclean -u
   $(RM) $(ALL_T) $(ALL_O)

depend:
   @$(CC) $(CFLAGS) -MM *.c

echo:
   @echo "CC = $(CC)"
   @echo "CFLAGS = $(CFLAGS)"
   @echo "AR = $(AR)"
   @echo "RANLIB = $(RANLIB)"
   @echo "RM = $(RM)"
   @echo "MYCFLAGS = $(MYCFLAGS)"
   @echo "MYLDFLAGS = $(MYLDFLAGS)"
   @echo "MYLIBS = $(MYLIBS)"
   @echo "DL = $(DL)"

$(ALL_O): makefile

# DO NOT EDIT
# automatically made with 'gcc -MM l*.c'

lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
 lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
 ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
 llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
 ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
 lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
 ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
 lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
 lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
 ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
 lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
 llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
 lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
 lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
 llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
 ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
 lvm.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
 llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
 ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
 lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
 lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
 lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
 llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltests.o: ltests.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
 lobject.h ltm.h lzio.h lmem.h lauxlib.h lcode.h llex.h lopcodes.h \
 lparser.h lctype.h ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h \
 lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
 llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
 lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
 lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
 llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
 ltable.h lvm.h ljumptab.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
 lobject.h ltm.h lzio.h

# (end of Makefile)


Copying that to makefile.ultibo.armv6 and putting it in the same folder as the lua source and then running the following commands (this is from a Linux command line) results in a liblua.a file that we can compile examples against.

Code: Select all

 cd lua
 export PATH=$HOME/gcc-arm-none-eabi-5_4-2016q2/bin:$PATH
 make --makefile=makefile.ultibo.armv6

The path to the arm-none-eabi folder should be adjusted to suit your setup.

Try this first and see if you get a better result, if you are using Pi2 or Pi3 (ARM7) then let me know and I'll provide the makefile for those instead,
Ultibo.org | Make something amazing
https://ultibo.org
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Fri Sep 14, 2018 7:27 am

Uhm could you post the makefile to pastebin or something? I think the forum removed tabs and it doesn't work
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Fri Sep 14, 2018 7:30 am

nevermind i got it :)
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Fri Sep 14, 2018 9:11 am

Ok, i had to hack a little to get your makefile to work, it references files like ltests.h that i don't have (i'm using lua-5.3.4, perhaps it's that, or maybe it's a file you made).

Also, i discovered something that could explain why the linker couldn't find luaL_loadfile. Here's how it's defined in the sources (at least for 5.3.4):

Code: Select all

LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);

#define luaL_loadfile(L,f)      luaL_loadfilex(L,f,NULL)


Yep, it's a macro. Indeed while i looked into liblua.a i noticed the function had an extra x, i tought maybe it was some error with the way i opened the file. I even try to call it but without the extra parameter and it crashed obviously. I'll retry this evening and i'm confident i'll be able to run it :P
pjde
Posts: 410
Joined: Tue Feb 09, 2016 6:21 am
Location: Sydney, Australia

Re: Integrating Lua

Postby pjde » Sun Sep 16, 2018 8:30 pm

This may be of some help.
Attachments
uLuaLib.zip
(3.93 KiB) Downloaded 24 times
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Mon Sep 17, 2018 7:06 am

thanks pjde!i don't think your unit is for the same lua version i'm using but i can surely copy/paste a lot from it.
I actually succeded in integrating it, was able to run lua code and call pascal function from lua, yay!
pjde
Posts: 410
Joined: Tue Feb 09, 2016 6:21 am
Location: Sydney, Australia

Re: Integrating Lua

Postby pjde » Sun Sep 30, 2018 1:38 am

Do you have an example you are willing to share?

Paul
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Sun Sep 30, 2018 6:01 am

Sure, i'll set up a repo, probably tomorrow if i can
msx80
Posts: 25
Joined: Thu Aug 02, 2018 8:38 am

Re: Integrating Lua

Postby msx80 » Mon Oct 01, 2018 8:43 am

here you are:

https://github.com/msx80/Lua4Ultibo/

Should be straighforward to use.
Lua4Ultibo
Integrate Lua 5.3.4 into your Ultibo project

Just include luaheaders.pas and put liblua.a in your library search path and it should work.

The example includes calling a pascal procedure with or without parameters.

The headers are incomplete, i only ported the main api calls and what i needed, but it's easy to expand. Tested only with Raspberry Pi Zero, but should work with others too.


@Ultibo feel free to use any of this in Ultibo if you need it

Return to “Libraries”

Who is online

Users browsing this forum: No registered users and 1 guest