mirror of
https://github.com/lua/lua.git
synced 2024-11-23 02:03:55 +08:00
New interface to function 'luaL_openselectedlibs'
Instead of preloading all non-loaded libraries, there is another mask to select which libraries to preload.
This commit is contained in:
parent
c8121ce34b
commit
165389b27b
22
linit.c
22
linit.c
@ -21,12 +21,12 @@
|
||||
|
||||
|
||||
/*
|
||||
** Standard Libraries
|
||||
** Standard Libraries. (Must be listed in the same ORDER of their
|
||||
** respective constants LUA_<libname>K.)
|
||||
*/
|
||||
static const luaL_Reg stdlibs[] = {
|
||||
{LUA_GNAME, luaopen_base},
|
||||
{LUA_LOADLIBNAME, luaopen_package},
|
||||
|
||||
{LUA_COLIBNAME, luaopen_coroutine},
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
{LUA_IOLIBNAME, luaopen_io},
|
||||
@ -35,30 +35,28 @@ static const luaL_Reg stdlibs[] = {
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_UTF8LIBNAME, luaopen_utf8},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** require selected standard libraries and add the others to the
|
||||
** preload table.
|
||||
** require and preload selected standard libraries
|
||||
*/
|
||||
LUALIB_API void luaL_openselectedlibs (lua_State *L, int what) {
|
||||
int mask = 1;
|
||||
LUALIB_API void luaL_openselectedlibs (lua_State *L, int load, int preload) {
|
||||
int mask;
|
||||
const luaL_Reg *lib;
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
for (lib = stdlibs; lib->func; (lib++, mask <<= 1)) {
|
||||
if (what & mask) { /* selected? */
|
||||
for (lib = stdlibs, mask = 1; lib->name != NULL; lib++, mask <<= 1) {
|
||||
if (load & mask) { /* selected? */
|
||||
luaL_requiref(L, lib->name, lib->func, 1); /* require library */
|
||||
lua_pop(L, 1); /* remove result from the stack */
|
||||
}
|
||||
else { /* add library to PRELOAD table */
|
||||
else if (preload & mask) { /* selected? */
|
||||
lua_pushcfunction(L, lib->func);
|
||||
lua_setfield(L, -2, lib->name);
|
||||
lua_setfield(L, -2, lib->name); /* add library to PRELOAD table */
|
||||
}
|
||||
}
|
||||
lua_assert((mask >> 1) == LUA_UTF8LIBK);
|
||||
lua_pop(L, 1); // remove PRELOAD table
|
||||
lua_pop(L, 1); /* remove PRELOAD table */
|
||||
}
|
||||
|
||||
|
5
ltests.c
5
ltests.c
@ -1223,8 +1223,9 @@ static lua_State *getstate (lua_State *L) {
|
||||
|
||||
static int loadlib (lua_State *L) {
|
||||
lua_State *L1 = getstate(L);
|
||||
int what = luaL_checkinteger(L, 2);
|
||||
luaL_openselectedlibs(L1, what);
|
||||
int load = luaL_checkinteger(L, 2);
|
||||
int preload = luaL_checkinteger(L, 3);
|
||||
luaL_openselectedlibs(L1, load, preload);
|
||||
luaL_requiref(L1, "T", luaB_opentests, 0);
|
||||
lua_assert(lua_type(L1, -1) == LUA_TTABLE);
|
||||
/* 'requiref' should not reload module already loaded... */
|
||||
|
2
lua.c
2
lua.c
@ -618,7 +618,7 @@ static void doREPL (lua_State *L) {
|
||||
/* }================================================================== */
|
||||
|
||||
#if !defined(luai_openlibs)
|
||||
#define luai_openlibs(L) luaL_openlibs(L)
|
||||
#define luai_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
||||
#endif
|
||||
|
||||
|
||||
|
8
lualib.h
8
lualib.h
@ -14,11 +14,11 @@
|
||||
/* version suffix for environment variable names */
|
||||
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||
|
||||
#define LUA_GK 1
|
||||
#define LUA_GLIBK 1
|
||||
LUAMOD_API int (luaopen_base) (lua_State *L);
|
||||
|
||||
#define LUA_LOADLIBNAME "package"
|
||||
#define LUA_LOADLIBK (LUA_GK << 1)
|
||||
#define LUA_LOADLIBK (LUA_GLIBK << 1)
|
||||
LUAMOD_API int (luaopen_package) (lua_State *L);
|
||||
|
||||
|
||||
@ -56,10 +56,10 @@ LUAMOD_API int (luaopen_utf8) (lua_State *L);
|
||||
|
||||
|
||||
/* open selected libraries */
|
||||
LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int what);
|
||||
LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int load, int preload);
|
||||
|
||||
/* open all libraries */
|
||||
#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0)
|
||||
#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -358,7 +358,7 @@ item = function (s)
|
||||
local t, p = string.match(s, "^([^\n|]+)|()")
|
||||
if t then
|
||||
s = string.sub(s, p)
|
||||
s = Tag.b(t..": ") .. s
|
||||
s = Tag.b(t) ..": " .. s
|
||||
end
|
||||
return Tag.li(fixpara(s))
|
||||
end,
|
||||
|
@ -664,7 +664,6 @@ Values equal to or less than 100 mean the collector will not wait to
|
||||
start a new cycle.
|
||||
A value of 200 means that the collector waits for
|
||||
the total number of objects to double before starting a new cycle.
|
||||
The default value is 200.
|
||||
|
||||
The garbage-collector step size controls the
|
||||
size of each incremental step,
|
||||
@ -672,7 +671,6 @@ specifically how many objects the interpreter creates
|
||||
before performing a step:
|
||||
A value of @M{n} means the interpreter will create
|
||||
approximately @M{n} objects between steps.
|
||||
The default value is 250.
|
||||
|
||||
The garbage-collector step multiplier
|
||||
controls the size of each GC step.
|
||||
@ -681,7 +679,6 @@ in each step, @M{n%} objects for each created object.
|
||||
Larger values make the collector more aggressive.
|
||||
Beware that values too small can
|
||||
make the collector too slow to ever finish a cycle.
|
||||
The default value is 200.
|
||||
As a special case, a zero value means unlimited work,
|
||||
effectively producing a non-incremental, stop-the-world collector.
|
||||
|
||||
@ -711,7 +708,6 @@ after the last major collection.
|
||||
For instance, for a multiplier of 20,
|
||||
the collector will do a minor collection when the number of objects
|
||||
gets 20% larger than the total after the last major collection.
|
||||
The default value is 25.
|
||||
|
||||
The minor-major multiplier controls the shift to major collections.
|
||||
For a multiplier @M{x},
|
||||
@ -721,7 +717,6 @@ than the total after the previous major collection.
|
||||
For instance, for a multiplier of 100,
|
||||
the collector will do a major collection when the number of old objects
|
||||
gets larger than twice the total after the previous major collection.
|
||||
The default value is 100.
|
||||
|
||||
The major-minor multiplier controls the shift back to minor collections.
|
||||
For a multiplier @M{x},
|
||||
@ -731,7 +726,6 @@ of the objects allocated during the last cycle.
|
||||
In particular, for a multiplier of 0,
|
||||
the collector will immediately shift back to minor collections
|
||||
after doing one cycle of major collections.
|
||||
The default value is 50.
|
||||
|
||||
}
|
||||
|
||||
@ -5885,13 +5879,6 @@ or @id{NULL} if there is a @x{memory allocation error}.
|
||||
|
||||
}
|
||||
|
||||
@APIEntry{void luaL_openlibs (lua_State *L);|
|
||||
@apii{0,0,e}
|
||||
|
||||
Opens all standard Lua libraries into the given state.
|
||||
|
||||
}
|
||||
|
||||
@APIEntry{
|
||||
T luaL_opt (L, func, arg, dflt);|
|
||||
@apii{0,0,-}
|
||||
@ -6073,7 +6060,7 @@ and sets the call result to @T{package.loaded[modname]},
|
||||
as if that function has been called through @Lid{require}.
|
||||
|
||||
If @id{glb} is true,
|
||||
also stores the module into the global @id{modname}.
|
||||
also stores the module into the global variable @id{modname}.
|
||||
|
||||
Leaves a copy of the module on the stack.
|
||||
|
||||
@ -6290,23 +6277,61 @@ Except for the basic and the package libraries,
|
||||
each library provides all its functions as fields of a global table
|
||||
or as methods of its objects.
|
||||
|
||||
To have access to these libraries,
|
||||
the @N{C host} program should call the @Lid{luaL_openlibs} function,
|
||||
which opens all standard libraries.
|
||||
}
|
||||
|
||||
|
||||
@sect2{lualib-h| @title{Loading the Libraries in C code}
|
||||
|
||||
A @N{C host} program must explicitly load
|
||||
the standard libraries into a state,
|
||||
if it wants its scripts to use them.
|
||||
For that,
|
||||
the host program can call the function @Lid{luaL_openlibs}.
|
||||
Alternatively,
|
||||
the host program can open them individually by using
|
||||
@Lid{luaL_requiref} to call
|
||||
@defid{luaopen_base} (for the basic library),
|
||||
@defid{luaopen_package} (for the package library),
|
||||
@defid{luaopen_coroutine} (for the coroutine library),
|
||||
@defid{luaopen_string} (for the string library),
|
||||
@defid{luaopen_utf8} (for the UTF-8 library),
|
||||
@defid{luaopen_table} (for the table library),
|
||||
@defid{luaopen_math} (for the mathematical library),
|
||||
@defid{luaopen_io} (for the I/O library),
|
||||
@defid{luaopen_os} (for the operating system library),
|
||||
and @defid{luaopen_debug} (for the debug library).
|
||||
These functions are declared in @defid{lualib.h}.
|
||||
the host can select which libraries to open,
|
||||
by using @Lid{luaL_openselectedlibs}.
|
||||
Both functions are defined in the header file @id{lualib.h}.
|
||||
@index{lualib.h}
|
||||
|
||||
The stand-alone interpreter @id{lua} @see{lua-sa}
|
||||
already opens all standard libraries.
|
||||
|
||||
@APIEntry{void luaL_openlibs (lua_State *L);|
|
||||
@apii{0,0,e}
|
||||
|
||||
Opens all standard Lua libraries into the given state.
|
||||
|
||||
}
|
||||
|
||||
@APIEntry{void luaL_openselectedlibs (lua_State *L, int load, int preload);|
|
||||
@apii{0,0,e}
|
||||
|
||||
Opens (loads) and preloads selected libraries into the state @id{L}.
|
||||
(To @emph{preload} means to add
|
||||
the library loader into the table @Lid{package.preload},
|
||||
so that the library can be required later by the program.
|
||||
Keep in mind that @Lid{require} itself is provided
|
||||
by the @emph{package} library.
|
||||
If a program does not load that library,
|
||||
it will be unable to require anything.)
|
||||
|
||||
The integer @id{load} selects which libraries to load;
|
||||
the integer @id{preload} selects which to preload, among those not loaded.
|
||||
Both are masks formed by a bitwise OR of the following constants:
|
||||
@description{
|
||||
@item{@defid{LUA_GLIBK} | the basic library.}
|
||||
@item{@defid{LUA_LOADLIBK} | the package library.}
|
||||
@item{@defid{LUA_COLIBK} | the coroutine library.}
|
||||
@item{@defid{LUA_STRLIBK} | the string library.}
|
||||
@item{@defid{LUA_UTF8LIBK} | the UTF-8 library.}
|
||||
@item{@defid{LUA_TABLIBK} | the table library.}
|
||||
@item{@defid{LUA_MATHLIBK} | the mathematical library.}
|
||||
@item{@defid{LUA_IOLIBK} | the I/O library.}
|
||||
@item{@defid{LUA_OSLIBK} | the operating system library.}
|
||||
@item{@defid{LUA_DBLIBK} | the debug library.}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -546,9 +546,9 @@ do
|
||||
]], source)
|
||||
collectgarbage()
|
||||
local m2 = collectgarbage"count" * 1024
|
||||
-- load used fewer than 350 bytes. Code alone has more than 3*N bytes,
|
||||
-- load used fewer than 400 bytes. Code alone has more than 3*N bytes,
|
||||
-- and string literal has N bytes. Both were not loaded.
|
||||
assert(m2 > m1 and m2 - m1 < 350)
|
||||
assert(m2 > m1 and m2 - m1 < 400)
|
||||
X = 0; code(); assert(X == N and Y == string.rep("a", N))
|
||||
X = nil; Y = nil
|
||||
|
||||
@ -1122,7 +1122,7 @@ assert(a == nil and c == 2) -- 2 == run-time error
|
||||
a, b, c = T.doremote(L1, "return a+")
|
||||
assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
|
||||
|
||||
T.loadlib(L1, 2) -- load only 'package'
|
||||
T.loadlib(L1, 2, ~2) -- load only 'package', preload all others
|
||||
a, b, c = T.doremote(L1, [[
|
||||
string = require'string'
|
||||
local initialG = _G -- not loaded yet
|
||||
@ -1141,7 +1141,7 @@ T.closestate(L1);
|
||||
|
||||
|
||||
L1 = T.newstate()
|
||||
T.loadlib(L1, 0)
|
||||
T.loadlib(L1, 0, 0)
|
||||
T.doremote(L1, "a = {}")
|
||||
T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
|
||||
settable -3]])
|
||||
@ -1524,7 +1524,7 @@ end
|
||||
|
||||
do -- garbage collection with no extra memory
|
||||
local L = T.newstate()
|
||||
T.loadlib(L, 1 | 2) -- load _G and 'package'
|
||||
T.loadlib(L, 1 | 2, 0) -- load _G and 'package'
|
||||
local res = (T.doremote(L, [[
|
||||
_ENV = _G
|
||||
assert(string == nil)
|
||||
|
@ -705,7 +705,7 @@ else
|
||||
|
||||
T.testC(state, "settop 0")
|
||||
|
||||
T.loadlib(state, 1 | 2) -- load _G and 'package'
|
||||
T.loadlib(state, 1 | 2, 4) -- load _G and 'package', preload 'coroutine'
|
||||
|
||||
assert(T.doremote(state, [[
|
||||
coroutine = require'coroutine';
|
||||
|
Loading…
Reference in New Issue
Block a user