【问题标题】:Is there a simple way to convert a lua table to a C++ array or vector?有没有一种简单的方法可以将 lua 表转换为 C++ 数组或向量?
【发布时间】:2020-11-18 15:14:21
【问题描述】:

我开始制作自己的包管理器并开始开发依赖系统。 构建文件是用 lua 编写的,它们看起来像这样:

package = {
  name = "pfetch",
  version = "0.6.0",
  source = "https://github.com/dylanaraps/pfetch/archive/0.6.0.tar.gz",
  git = false
}

dependencies = {
   "some_dep",
   "some_dep2"
}

function install()
  quantum_install("pfetch", false)
end

唯一的问题,我不知道如何转换

dependencies = {
   "some_dep",
   "some_dep2"
}

到一个全局 c++ 数组:["some_dep", "some_dep2"] 列表中任何作为字符串无效的内容都应被忽略。 有什么好方法可以做到这一点? 提前致谢

注意:我使用 C api 与 C++ 中的 lua 进行交互。不知道Lua的错误是使用longjmp还是C++异常。

【问题讨论】:

  • 没有简单的方法。 1) 将每个 Lua 字符串推入 C API 栈并转换为 C 指针lua_gettable + lua_tostring; 2)创建C数组; 3) 将 C 数组传递给 C 函数; 4) 只有在 C 函数退出后,您才能从 C API 堆栈中弹出所有 Lua 字符串。
  • 这能回答你的问题吗? Convert Lua table to C array?
  • @Nifim - 使用字符串(与数字不同)时,您必须考虑 GC 可能带来的“惊喜”。
  • 这很好,我没有真正想过一个字符串数组会如何使它成为一个不同的野兽。
  • 你想对数组/向量做什么?立即对其进行操作然后丢弃它,将其保存到 C++ 全局或其他东西,或者将其作为用户数据传回 Lua?另外,您的 Lua 是否使用 C++ 编译,以便错误使用异常而不是 longjmp?如果列表中包含无效的内容,该怎么办?

标签: lua package-managers lua-c++-connection


【解决方案1】:

根据您评论中的说明,这样的事情对您有用:

#include <iostream>
#include <string>
#include <vector>
#include <lua5.3/lua.hpp>

std::vector<std::string> dependencies;

static int q64795651_set_dependencies(lua_State *L) {
    dependencies.clear();
    lua_settop(L, 1);
    for(lua_Integer i = 1; lua_geti(L, 1, i) != LUA_TNIL; ++i) {
        size_t len;
        const char *str = lua_tolstring(L, 2, &len);
        if(str) {
            dependencies.push_back(std::string{str, len});
        }
        lua_settop(L, 1);
    }
    return 0;
}

static int q64795651_print_dependencies(lua_State *) {
    for(const auto &dep : dependencies) {
        std::cout << dep << std::endl;
    }
    return 0;
}

static const luaL_Reg q64795651lib[] = {
    {"set_dependencies", q64795651_set_dependencies},
    {"print_dependencies", q64795651_print_dependencies},
    {nullptr, nullptr}
};

extern "C"
int luaopen_q64795651(lua_State *L) {
    luaL_newlib(L, q64795651lib);
    return 1;
}

演示:

$ g++ -fPIC -shared q64795651.cpp -o q64795651.so
$ lua5.3
Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> q64795651 = require('q64795651')
> dependencies = {
>>    "some_dep",
>>    "some_dep2"
>> }
> q64795651.set_dependencies(dependencies)
> q64795651.print_dependencies()
some_dep
some_dep2
>

一个重要的陷阱:由于您不确定 Lua 是否被编译为使用 longjmp 或其错误异常,您需要确保在 Lua 错误可能出现的任何地方都没有任何带有析构函数的自动变量发生。 (在我的答案中的代码中已经是这种情况;只需确保在将其合并到程序中时不会意外添加任何此类位置。)

【讨论】:

  • 谢谢!有效。你能澄清一下你最后说的话吗?我仍然是 C++ 初学者,但承担大型项目很有趣。
  • @ChocolateMeteor Lua 可以编译为使用 setjmp()/longjmp() 或 C++ 异常来处理错误。 setjmp()/longjmp() do not play well in C++。如果你的 Lua 是用 setjmp()/longjmp() 编译的并且你不能改变它,那么你需要非常小心,不要在发生 Lua 错误时意外允许 Undefined Behavior。
  • 好的,谢谢!还有一个菜鸟问题:我将如何调整您的代码以接受像 this 这样的文件(它从第二个变量中获取依赖项)注意:我已经做到了,所以它可以处理除依赖项部分之外的所有内容
  • @ChocolateMeteor 所以不是将表格作为参数,而是想从名为dependencies 的 Lua 全局读取它?如果是这样,则将第一个lua_settop(L, 1); 替换为lua_settop(L, 0); lua_getglobal(L, "dependencies");
猜你喜欢
  • 2010-09-06
  • 1970-01-01
  • 2022-09-24
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 2010-09-17
  • 2021-03-13
  • 2010-11-14
相关资源
最近更新 更多