关于C#:省略Lua标准库的最佳方法?

Best way to omit Lua standard libraries?

删除或省略Lua标准库软件包的最佳方法是什么?例如,在特定环境中删除os库函数。有问题的项目正在从源文件构建Lua,因此我可以编辑源代码,尽管如果可能的话,我宁愿通过API进行操作。


请参阅源工具包中的文件luaconf.h,以轻松访问大多数编译时配置,例如lua_Number所使用的实际类型。

有关通过调用luaL_openlibs()加载的核心库的列表,请参阅源工具包中的文件linit.c

常见的做法是将该文件复制到应用程序的源,并根据需要对其进行修改,并调用该副本的luaL_openlibs()代替核心版本。如果要私下编译Lua而不是链接到库的预构建二进制文件之一,则可以找到一种方法来满足您的需要。

当然,您也不需要编译或链接到选择离开luaL_openlibs()的任何库(例如loslib.c中的os)。

您可能无法完全遗漏的唯一库是提供pairs()ipairs()pcall()tostring()之类的内容的基本库,如果没有这些库,可能会有很多不便之处。当移植到其中一些有问题的环境时,通常最好仔细查看它在lbaselib.c中的实现,并修剪其中的功能或重新实现功能以满足您的需求。

编辑:

在解释器中包含不同库列表的另一种方法是根本不调用luaL_openlibs()。尽管提供了便利,但像所有辅助库一样,luaL_openlibs()不是必需的。而是显式地仅打开所需的库。

参考手册的第5章对此进行了讨论:

To have access to these libraries, the
C host program should call the
luaL_openlibs function, which opens
all standard libraries. Alternatively,
it can open them individually by
calling luaopen_base (for the basic
library), luaopen_package (for the
package library), luaopen_string (for
the string library), luaopen_table
(for the table library), luaopen_math
(for the mathematical library),
luaopen_io (for the I/O library),
luaopen_os (for the Operating System
library), and luaopen_debug (for the
debug library). These functions are
declared in lualib.h and should not be
called directly: you must call them
like any other Lua C function, e.g.,
by using lua_call.

最后一句话有时是麻烦的根源,因为旧版本的Lua没有该限制。每个单独模块的luaopen_xxx()函数都遵循require函数所使用的相同协议。应该为它传递一个参数:一个字符串,其中包含已知模块的名称。基本模块是一个例外,它传递了一个空字符串,因为它没有实际名称。

这是一个创建新Lua状态并仅打开基本库和包库的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include"lua.h"
#include"lualib.h"
#include"lauxlib.h"

lua_State *CreateBasicLua() {
    lua_State *L;

    L = luaL_newstate();
    if (L) {
        lua_pushcfunction(L, luaopen_base);
        lua_pushstring(L,"");
        lua_call(L, 1, 0);
        lua_pushcfunction(L, luaopen_package);
        lua_pushstring(L, LUA_LOADLIBNAME);
        lua_call(L, 1, 0);
    }
    return L;
}

成功返回新的lua_State,失败返回新的NULL


假设您只想打开basepackage库。在Lua 5.2中,最简洁的方法是

1
2
3
luaL_requiref(L,"_G", luaopen_base, 1);
luaL_requiref(L,"package", luaopen_package, 1);
lua_pop(L, 2);

这是linit.c中的luaL_openlibs函数的工作方式,除了它可以加载所有内容。


我认为该帖子回答了您的问题,但是有关该主题的更多信息。
请注意,您也可以只对整个表"零"。

因此在您的示例" os"库中,您可以执行" os = nil"然后是poof!," os"库/表已消失。
在此示例之后执行" os.time()"将为现在不存在的lib /表返回错误。
此外,如果您只想在" os"中单独使用" time"方法,则可以执行" os.time = nil"。