C 省略Lua标准库的最佳方法?

C 省略Lua标准库的最佳方法?,c,lua,C,Lua,删除或省略Lua标准库包的最佳方法是什么?例如,在特定环境中删除。所讨论的项目是从源文件构建Lua,这样我就可以编辑源代码,不过如果可能的话,我更愿意通过API进行编辑。请参阅源代码工具包中的文件luaconf.h,以便轻松访问大多数编译时配置,例如Lua\u编号的实际类型 有关通过调用luaL\u openlibs()加载的核心库列表,请参阅源代码工具包中的文件linit.c 通常的做法是将该文件复制到应用程序的源代码中,并根据需要对其进行修改,调用该副本的luaL\u openlibs(),

删除或省略Lua标准库包的最佳方法是什么?例如,在特定环境中删除。所讨论的项目是从源文件构建Lua,这样我就可以编辑源代码,不过如果可能的话,我更愿意通过API进行编辑。

请参阅源代码工具包中的文件
luaconf.h
,以便轻松访问大多数编译时配置,例如
Lua\u编号的实际类型

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

通常的做法是将该文件复制到应用程序的源代码中,并根据需要对其进行修改,调用该副本的
luaL\u openlibs()
,以代替核心版本。如果您是在私下编译Lua,而没有链接到库中的一个预构建二进制文件,那么您可以找到一种方法来执行适合您需要的等效操作

当然,您也不需要编译或链接到任何库的源代码(例如
os
,可以在
loslib.c
中找到),这些库是您选择从
luaL\u openlibs()
中删除的

唯一一个您可能无法完全忽略的库是基本库,它提供了诸如
pairs()
ipairs()
pcall()
tostring()
,以及许多其他不方便使用的功能。当移植到其中一些功能有问题的环境时,通常最好仔细查看它在
lbaselib.c
中的实现,或者从中裁剪功能,或者重新实现它们以满足您的需要

编辑:

在解释器中包含不同库列表的另一种方法是根本不调用
luaL\u openlibs()
。与所有辅助库一样,
luaL\u openlibs()
虽然是为了方便起见而提供的,但不是强制性的。相反,只显式打开所需的库

《参考手册》的第二部分谈到了这一点:

要访问这些库,请 C主机程序应该调用
luaL\u openlibs
函数,打开 所有标准库。或者, 它可以通过以下方式单独打开它们: 调用
luaopen\u base
(用于基本 库),
luaopen\u包
(用于 软件包库),
luaopen\u字符串
(用于 字符串库),
luaopen\u表
(对于表库),
luaopen\u math
(对于数学图书馆),
luaopen\u io
(用于I/O库),
luaopen\u os
(用于操作系统 库)和
luaopen\u debug
(用于 调试库)。这些功能是 在
lualib.h
中声明,不应 直接打电话:你必须打电话给他们 与任何其他Lua C函数一样,例如。, 通过使用
lua\u调用

最后一句话偶尔会引起麻烦,因为Lua的旧版本没有这一限制。每个模块的
luaopen_xxx()
函数遵循
require
函数使用的相同协议。应该向它传递一个参数:一个包含模块名称的字符串。基本模块是一个例外,它被传递一个空字符串,因为它没有实际名称

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

#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\u状态
,失败时返回
NULL

我想这篇文章回答了你的问题,但提供了更多关于这个主题的信息。 请注意,您也可以“nil”整个表

因此,在您的示例“os”库中,您可以执行一个“os=nil”,然后poof!,“os”库/表不见了。 在此示例之后执行“os.time()”将为现在不存在的库/表返回一个错误。
此外,如果您只想在“os”中单独禁用“time”方法,您可以只执行“os.time=nil”。

假设您只想打开
基本库和
库。在Lua5.2中,最简洁的方式是

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

这就是
linit.c
中的luaL_openlibs函数的工作方式,只是它加载所有内容。

这似乎是正确的方式。很遗憾,我们必须在Lua源代码中编辑一个c文件(或在您的项目中编辑一个副本)来配置标准库。我添加了一个代码片段,演示了编辑linit.c的另一种方法,以获得您想要的自定义。简言之,因为手册上说要这样做。“这些函数在lualib.h中声明,不应直接调用:您必须像调用任何其他Lua C函数一样调用它们,例如,使用Lua_调用。”(Lua参考手册,第5章,第65页)。luaopen_xxx()函数被保证像其他任何C函数一样被调用,具有干净的堆栈,可以容纳通常数量的临时变量。直接调用它并不能让内核做出这些保证。只有当通过
包中的模式可以访问某些DLL时,才可以使用
require“foo”
。cpath
包含一个名为
luaopen\u foo()的函数,该函数在调用时的行为与预期一致。默认情况下,在任何此类DLL中都找不到基本库,因为它们是在Lua核心中编译的。但是,如果您知道在哪里查找,则可以使用
package.loadlib()
加载它们。还有第三方模块,如alien和ffi,可以提供在任何DLL中调用任意函数的功能。简言之,请注意脚本调用的内容。此代码示例中的三元组(pushcfunction/pushstring/call)基本上是luaL_requiref()的缩写版本,如果您使用的是5.2,则可能需要使用它。请参阅lua源代码树中的lauxlib.c。注意,如果这是您唯一要做的事情,那么用户可以通过
os=require(“os”)
轻松地将其取回。您必须禁止加载库!还有,如果目标