我想通过调用lua_setfenv()在自己的环境中执行不受信任的.lua文件,这样它就不会影响我的任何代码.
该功能的文档虽然只解释了如何调用函数,而不是如何执行文件.
目前运行我使用的文件:
int error = luaL_loadfile(mState, path.c_str()) || lua_pcall(mState, 0, 0, 0);
Run Code Online (Sandbox Code Playgroud)
我是否必须使用C API调用"dofile"lua函数lua_setfenv,或者是否有更优雅的方法来执行此操作?
我的 C 程序可能有一个愚蠢的错误。在某个点上,Lua 堆栈不包含我认为应该包含的值。
为了调试它,我想在程序的某个点打印Lua堆栈的内容。我怎样才能做到这一点而不弄乱进程中的堆栈?
我一直在寻找有关魔兽世界插件API的第一手信息。有几个不错的Wiki,但是它们的参考链接仅指向内部。当然,暴雪发布了一些有关该主题的信息。
是否可以从逆向工程和论坛中真正收集他们的所有信息?我很难相信这一点。
下面是我需要从C读取的lua表:
listen = {
{ port = 1234, address = "192.168.1.1", userdata = "liunx" },
{ port = 1235, address = "192.168.1.2", userdata = "liunx1" },
{ port = 1236, address = "192.168.1.3", userdata = "liunx2" }
}
Run Code Online (Sandbox Code Playgroud)
下面是c代码:
#include <lua.h> /* Always include this when calling Lua */
#include <lauxlib.h> /* Always include this when calling Lua */
#include <lualib.h> /* Prototype for luaL_openlibs(), */
/* always include this when calling Lua */
#include <stdlib.h> /* For function exit() …Run Code Online (Sandbox Code Playgroud) 使用 Lua C API,我Object向 Lua 注册了一个简单的类,如下所示:
// My C++ Object class
class Object {
private:
double x;
public:
Object(double x) : x(x){}
};
// Create and return instance of Object class to Lua
int object_new(lua_State* L)
{
double x = luaL_checknumber(L, 1);
*reinterpret_cast<Object**>(lua_newuserdata(L, sizeof(Object*))) = new Object(x);
luaL_setmetatable(L, "Object");
return 1;
}
// Functions to register to Lua
const luaL_Reg functions[] =
{
{"new", object_new},
{nullptr, nullptr}
};
// Register the Object class to Lua
luaL_newmetatable(L, "Object");
luaL_setfuncs(L, …Run Code Online (Sandbox Code Playgroud) 我目前正在学习如何使用 Lua C API,虽然我在 C/C++ 和 Lua 之间成功绑定了函数,但我有几个问题:
将多个脚本加载到一个中是个好主意lua_State吗?有没有办法关闭特定的块?如果不再使用脚本,如何lua_State在保留其他所有内容的同时将其清除?
使用可能对函数/全局变量使用相同名称的脚本的最佳方法是什么?如果我加载所有这些,新的定义会覆盖旧的。
在线阅读后,我认为我需要将每个加载的块分离到不同的环境中。我设想的这种工作方式是每次加载一个块时,我都会为它分配一个唯一的环境名称,当我需要使用它时,我只需使用该名称从 中获取环境LUA_REGISTRYINDEX并执行操作。到目前为止,我还没有想出如何做到这一点。网上有例子,但他们使用 Lua 5.1。
如何从C-API创建Lua表,如下所示:
TableName = {a, b, c}
Run Code Online (Sandbox Code Playgroud)
如何设置表名?我只知道如何创建表和put值,但不知道如何设置表的名称.
创建没有名称的表的代码:
lua_createtable(L, 0, 3);
lua_pushnumber(L, 1);
lua_setfield(L, -2, "a");
lua_pushnumber(L, 2);
lua_setfield(L, -2, "b");
lua_pushnumber(L, 3);
lua_setfield(L, -2, "c");
Run Code Online (Sandbox Code Playgroud) 我用C语言编写了一个用于Lua的userdata类型.它有一些数组类型属性和各种方法.现在,如果你是这种类型,我使用u:set(k,v)resp.u:get(k)访问数据和例如u:sort()作为方法.为此,我设置__index了一个包含这些方法的表.现在,如果我想用访问数据u[k] = v或者u[k],我需要设置__newindex和__index对setRESP get.但是其他方法再也无法访问了......
在C中处理这个问题的最佳方法是什么?我猜我需要在C中编写一个函数来注册,__index并以某种方式在那里处理它.也许检查密钥是否属于Lua方法表,如果是,则调用它.
任何帮助/提示将不胜感激.我没有找到这样的例子,虽然这对我来说似乎是很自然的事情.
编辑: 在Lua中添加了我的C版解决方案,在下面的答案中发布.这或多或少都是直接翻译,所以所有功劳都归功于@ gilles-gregoire.
以下C函数注册为__index元方法.
static int permL_index(lua_State *L) {
struct perm **pp = luaL_checkudata(L, 1, PERM_MT);
int i;
luaL_getmetatable(L, PERM_MT);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if ( lua_isnil(L, -1) ) {
/* found no method, so get value from userdata. */
i = luaL_checkint(L, 2);
luaL_argcheck(L, 1 <= i && i <= (*pp)->n, 2, …Run Code Online (Sandbox Code Playgroud) 我有一个使用 userdata 对象运行良好的脚本系统。但是,我现在想在我的 userdata 上拥有一个可以使用常规表的属性。
我认为我应该做的是创建一个普通表并将元表设置为使用我当前的一组元方法,但是我很难理解如何做到这一点 - 我确定这是一个简单的调整,我只是看不到它现在。
我现有的代码看起来像:
void
LuaContext::push(lua_State* state, boost::shared_ptr<LuaWrapped> wrapped) {
static struct luaL_Reg methods[] = {
{ "__index", LuaWrapped::static_get },
{ "__newindex", LuaWrapped::static_set },
{ "__len", LuaWrapped::static_len },
{ "__ipairs", LuaWrapped::static_ipairs },
{ "__pairs", LuaWrapped::static_pairs },
{ "__gc", LuaWrapped::static_gc },
{ "__eq", LuaWrapped::static_eq },
{ NULL, NULL }
};
LuaWrapped::Ptr **ptr = (LuaWrapped::Ptr **)lua_newuserdata(state, sizeof(LuaWrapped::Ptr *));
*ptr = new LuaWrapped::Ptr(wrapped);
if (luaL_newmetatable(state, "LuaWrapped")) {
lua_pushstring(state, "__index");
lua_pushvalue(state, -2);
lua_settable(state, -3);
luaL_openlib(state, NULL, methods, 0);
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试遍历Lua中的表并输出:
这是代码:
void print_table(lua_State *L)
{
lua_pushnil(L);
while(lua_next(L, -2) != 0) {
const char *key = lua_tostring(L, -2);
if(lua_isstring(L, -1))
printf("%s = %s", key, lua_tostring(L, -1));
else if(lua_isnumber(L, -1))
printf("%s = %d", key, lua_tonumber(L, -1));
else if(lua_istable(L, -1)) {
printf("%s", key);
PrintTable(L);
}
lua_pop(L, 1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我尝试输出的表之一的示例:
s = {
p = {
n = "D",
g = "1",
},
d = {
l = "N",
p = "N",
u = "O",
po = 100,
}, …Run Code Online (Sandbox Code Playgroud)