c++ - 覆盖要求后调用 `lua_getfield()` 时崩溃

标签 c++ lua require

这个问题与@Henri_Menke 对这个问题的回答有关:How to get preloaded module name in C++

我试图用我自己的版本覆盖 require 函数,这样我就可以在 Lua 脚本中获取预加载的模块名称。

这是我的代码:

#include "lua.hpp"

void main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_settop(L, 0);
    luaL_dostring(L, "local require_original = require\n"
                     "function require(name, ...)\n"
                         "current_module = name\n"
                         "require_original(name, ...)\n"
                         "current_module = nil\n"
                     "end\n"); //if I comment out this chunk, it works fine
    luaL_dostring(L, "package.preload['test'] = function ()\n"
                         "local test = {}\n"
                         "print('While loading:', current_module)\n"
                         "function test.update() print('Updated!') end\n"
                         "return test\n"
                     "end\n");
    lua_getglobal(L, "require");
    lua_pushstring(L, "test");
    if (lua_pcall(L, 1, LUA_MULTRET, 0))
    {
        std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
        lua_pop(L, 1);
    }
    int top = lua_gettop(L);
    lua_getfield(L, -1, "update"); //crashes here
    if (lua_isfunction(L, -1))
    {
        lua_pushnil(L);
        if (lua_pcall(L, 1, LUA_MULTRET, 0))
        {
            std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
            lua_pop(L, 1);
        }
    }
    lua_close(L);
}

但是,调用 lua_getfield(L, -1, "update"); 时会崩溃。

当我注释掉第一段 Lua 脚本(第一个 luaL_dostring)时,它不再崩溃。

我不明白为什么如果我使用我自己的 require 版本它会崩溃。

我该如何解决这个问题?

最佳答案

我忘记从重写的 require 函数中返回模块表。对此感到抱歉。

#include <iostream>
#include "lua.hpp"

int main() {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_settop(L, 0);
    luaL_dostring(L, "local require_original = require\n"
                     "function require(name, ...)\n"
                         "current_module = name\n"
                         "local val = table.pack(require_original(name, ...))\n"
                         "current_module = nil\n"
                         "return table.unpack(val,1,val.n)\n"
                     "end\n"); //if I comment out this chunk, it works fine
    luaL_dostring(L, "package.preload['test'] = function ()\n"
                         "local test = {}\n"
                         "print('While loading:', current_module)\n"
                         "function test.update() print('Updated!') end\n"
                         "return test\n"
                     "end\n");
    lua_getglobal(L, "require");
    lua_pushstring(L, "test");
    if (lua_pcall(L, 1, LUA_MULTRET, 0))
    {
        std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
        lua_pop(L, 1);
    }
    int top = lua_gettop(L);
    lua_getfield(L, -1, "update"); //crashes here
    if (lua_isfunction(L, -1))
    {
        lua_pushnil(L);
        if (lua_pcall(L, 1, LUA_MULTRET, 0))
        {
            std::cout << "Error: " << lua_tostring(L, -1) << std::endl;
            lua_pop(L, 1);
        }
    }
    lua_close(L);
}
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 test.cpp -llua5.2
test.cpp:28:9: warning: unused variable 'top' [-Wunused-variable]
    int top = lua_gettop(L);
        ^
1 warning generated.
$ ./a.out 
While loading:  test
Updated!

关于c++ - 覆盖要求后调用 `lua_getfield()` 时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51520697/

相关文章:

c++ - 没有 GetFilePointer(Ex) Windows API 函数吗?

javascript - 在 JavaScript 中传递多个可选参数

git - 我应该在 node_modules 中克隆一个 Node 库来修改它吗?

C++:istream如何在条件表达式中转换为bool

java - Apache Qpid/Redhat MRG - 以可移植的方式跨不同系统发送日期

security - Lua - 我如何在不改变 GetFenv 函数的情况下欺骗它?

c++ - luabind : Accessing an invalidated c++ object from lua results in access violation

ruby-on-rails - `end_with?' :String (NoMethodError) 的未定义方法 "no such file to load -- Win32API"

angular - 如何在 Angular 中动态呈现 Markdown 文件?

c++ - 多久*投工作