lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi Everyone,

First off, I am sorry for the length of the email. Second Mark's suggestion is a great suggestion and very clean/simple maybe I should have used his design. But like most programmers I have my own ideas and maybe I should have used my time on other pursuits :-).

Mark Meijer wrote:
Just a thought, perhaps just for Keith Wiles and perhaps for a future standard distribution. It might be useful to have luaL_openlibs accept a luaL_Reg as an additional argument, instead of having it rely on the global static array in linit.c, as it is now. Or perhaps the best of both, having it use the global one in linit.c by default if the additional argument is NULL. It might look something like this in linit.c:

LUALIB_API void luaL_openlibs (lua_State *L, luaL_Reg* customlualibs) { /* Only these two */ const luaL_Reg *lib = customlualibs? customlualibs: lualibs; /* lines were changed. */
    for (; lib->func; lib++) {
        lua_pushcfunction(L, lib->func);
        lua_pushstring(L, lib->name);
        lua_call(L, 1, 0);
    }
}


This way, the application developer can choose to just pass NULL for the default behaviour and be done with it, or first do a call with NULL and then one for his own additional libraries, or only one (or several) call(s) for a completely customized selection of libraries.

Greets,
Mark


I was looking at the issues around using Lua in an embedded device with many different developers and projects. I have a set of changes which allow the developer to compile all of the src directory into one archive and use this archive on different projects without having to change anything within the src directory. While still being compatible to the default builds. I understand linit.c was designed to be copied and modified, but I believe we can alter the design of the code so it will not require changes directly.

My goals:
- Be able to alter the default libraries for each project without editing source code for each project. Allowing for scalability of the final image, by reducing undesired features. - Be able to add extra features without editing the linit.c for every project or keeping a copy of linit.c in each project. - Be able to distribute the archive to different projects, if the projects are similar in architecture. Note: different projects may require different luaconf.h because of different architectures.

First we add a few new defines to luaconf.h:
----------------------------------------------
/*
@@ LUA_MAIN define to your entry point or defaults to 'main'
** Change this define if you need a different entry point into your application.
** Look into lua.c for usage.
*/
#undef LUA_MAIN
#ifndef LUA_MAIN
#define LUA_MAIN        main
#endif /* LUA_MAIN */

/*
@@ LUAC_MAIN define to your entry point or defaults to 'main'
** Change this define if you need a different entry point into your application.
** Look into luac.c for usage.
*/
#undef LUAC_MAIN
#ifndef LUAC_MAIN
#define LUAC_MAIN        main
#endif /* LUA_MAIN */
------------------------------------------------
Within the RTOS (Note: RTOS system is a flat memory model) I am using 'main' is not used and could have link errors due to duplicate symbols, which means I need to rename 'main' to some other function name. In lua.c and luac.c I replaced main with LUA_MAIN or LUAC_MAIN. The default will be main if the developer does not turn on the defines. It is possible that luac or LUAC_MAIN is not required, but maybe someone would use it within single image???

With this setup I can have lua (shell) as a callable entry point from within the code. Which means I can have a telnet server spawn the lua shell for each telnet connection. Note: I did not change lua.c except as noted for LUA_MAIN.
------------------------------------------------

/*
@@ INCLUDE_DEFAULT_LIBS is the default set of Lua libraries.
** CHANGE to be undefined if needing a different set of libraries.
*/
#define INCLUDE_DEFAULT_LIBS
#ifdef INCLUDE_DEFAULT_LIBS
/*
@@ DEFAULT_LUA_LIBS is the standard set of libraries for Lua.
** CHANGE the 'else' side define for a different set of libraries and
** undefine the INCLUDE_DEFAULT_LIBS define. Look in linit.c for usage.
*/
#define DEFAULT_LUA_LIBS                    \
   {"",                luaopen_base},      \
   {LUA_TABLIBNAME,    luaopen_table},     \
   {LUA_IOLIBNAME,     luaopen_io},        \
   {LUA_OSLIBNAME,     luaopen_os},        \
   {LUA_STRLIBNAME,    luaopen_string},    \
   {LUA_MATHLIBNAME,   luaopen_math},      \
   {LUA_DBLIBNAME,     luaopen_debug},     \
   {LUA_LOADLIBNAME,   luaopen_package},   \
   { NULL, NULL }
#else
/*
** Add your default set of libraries to this define. Already picked
** a few common ones, but this define could be {NULL, NULL} only.
*/
#define DEFAULT_LUA_LIBS                    \
   {"",                luaopen_base},      \
   {LUA_TABLIBNAME,    luaopen_table},     \
   {LUA_IOLIBNAME,     luaopen_io},        \
   {LUA_STRLIBNAME,    luaopen_string},    \
   {LUA_LOADLIBNAME,   luaopen_package},   \
   { NULL, NULL }
#endif /* INCLUDE_DEFAULT_LIBS */
--------------------------------------------

With INCLUDE_DEFAULT_LIBS not defined the macro DEFAULT_LUA_LIBS is set to the libraries which were in linit.c file. This allows for the default configuration, but allows the developer to define a new set of defaults at compile time for all builds.
--------------------------------------------
/*
@@ HAVE_CUSTOM_LIBS define if needing to add custom libraries.
** CHANGE the macro to be defined if custom libraries are required. Alter the
** macro luaL_customlibs() to call the user defined function.
**
** The minimum user defined function would something like this:
** void addCustomLibs(lua_State *L) {
**   const luaL_Reg myLibs[] = { {"foo", foobar}, {NULL, NULL} };
**   luaL_addlibs(L, myLibs);
** }
*/
#undef HAVE_CUSTOM_LIBS
#ifdef HAVE_CUSTOM_LIBS
/* Would like to define the prototype as:
*    extern void addCustomLibs(lua_State *L);
* But lua_State is unknown at this point.
*/
extern void addCustomLibs(void * L);
#define luaL_customlibs(L)        addCustomLibs(L)
#else
#define luaL_customlibs(L)
#endif /* HAVE_CUSTOM_LIBS */
--------------------------------------------------

The HAVE_CUSTOM_LIBS if defined will allow the developer to add a routine to call from linit.c/luaL_openLibs() for any extra libraries he would like to add. Because the call is made from the luaL_openLibs() context it allows the developer to easily append more libraries within the correct context.

New linit.c file.
-------------------------------------------------------------------
/*
** $Id: linit.c,v 1.13 2005/08/26 17:36:32 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/

#define linit_c
#define LUA_LIB

#include "lua.h"

#include "lualib.h"
#include "lauxlib.h"

LUALIB_API void luaL_addlibs (lua_State *L, const luaL_Reg * lib) {
 for (; lib && lib->func; lib++) {
   lua_pushcfunction(L, lib->func);
   lua_pushstring(L, lib->name);
   lua_call(L, 1, 0);
 }
}

LUALIB_API void luaL_openlibs (lua_State *L) {
 const luaL_Reg lualibs[] = { DEFAULT_LUA_LIBS };
 luaL_addlibs(L, lualibs);
 luaL_customlibs(L);
}
---------------------------------------------------

The lualibs variable is now a local variable to luaL_openLibs() routine. With the use of DEFAULT_LUA_LIBS the developer can setup his system wide set of libraries and does not have to edit linit.c or have a private copy of the file.

The new API luaL_addlibs() allows the developer to add libraries easily. The new macro luaL_customlibs() allows the developer to add his libraries as he see fit by calling luaL_addlibs() or doing all of the work himself.

I believe this method only requires the developer to edit luaconf.h once and then compile the source code into an archive, which can be distributed to the different projects.

Comments?

PS. I did not show the mods to lua.c, luac.c and lauxlib.h which were all one line changes for 'main' or adding the luaL_addlibs() prototype.

PPS. I am also trying to figure out how the addCustomLibs() routine can be different for each application calling luaL_openlibs(). The only way I see it working is changing luaL_openlibs() to pass in a function pointer to call, but it would change the API and a few other files (like lua.c)??? Maybe someone see a better way.

Thanks for your time,
--Keith