1

I am starting to make my own package manager and am starting to develop a dependency system. The builfiles are written in lua, they look something like this:

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

Only problem,I have no idea how to convert

dependencies = {
   "some_dep",
   "some_dep2"
}

To a global c++ array: ["some_dep", "some_dep2"] Anything in the list that's not valid as a string should be ignored. Any good way to do this? Thanks in advance

Note: I am using the C api to interface with lua in C++. I don't know whether Lua's errors use longjmp or C++ exceptions.

RhinoCodes
  • 71
  • 7
  • No simple way. 1) Push each Lua string to C API stack and convert to C pointer `lua_gettable + lua_tostring`; 2) Create C array; 3) Pass C array to C function; 4) Only after C function exits you can pop all your Lua strings from C API stack. – Egor Skriptunoff Nov 11 '20 at 23:41
  • Does this answer your question? [Convert Lua table to C array?](https://stackoverflow.com/questions/11662650/convert-lua-table-to-c-array) – Nifim Nov 11 '20 at 23:41
  • @Nifim - When working with strings (unlike numbers), you have to think about possible "surprises" from GC. – Egor Skriptunoff Nov 11 '20 at 23:45
  • That's a good point, i hadn't really thought about how an array of strings would make this a different beast. – Nifim Nov 11 '20 at 23:47
  • What do you want to do with the array/vector? Operate on it immediately then discard it, save it to a C++ global or something, or pass it back into Lua as a userdata? Also, is your Lua compiled with C++ so that errors use exceptions instead of longjmp? And what should happen if the list has something invalid in it? – Joseph Sible-Reinstate Monica Nov 12 '20 at 03:48
  • @JosephSible-ReinstateMonica 1. I want the array to become a C++ global 2. No idea 3. The invalid thing would be ignored – RhinoCodes Nov 12 '20 at 22:14

1 Answers1

1

Based on the clarification in your comment, something like this will work for you:

#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;
}

Demo:

$ 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
>

One important pitfall: since you're not sure if Lua is compiled to use longjmp or exceptions for its errors, you need to make sure that you don't have any automatic variables with destructors anywhere that a Lua error could happen. (This is already the case in the code in my answer; just make sure you don't accidentally add any such places when incorporating this into your program.)

  • Thank you! It worked. Can you clarify on what you said at the end? I'm still a c++ beginner but it's fun to take on large projects. – RhinoCodes Nov 12 '20 at 22:43
  • 1
    @ChocolateMeteor Lua can be compiled to either use `setjmp()`/`longjmp()` or C++ exceptions for its errors. [`setjmp()`/`longjmp()` do not play well in C++](https://stackoverflow.com/q/1376085/7509065). If your Lua is compiled with `setjmp()`/`longjmp()` and you can't change it, then you need to be very careful not to accidentally allow Undefined Behavior if a Lua error happens. – Joseph Sible-Reinstate Monica Nov 12 '20 at 22:55
  • Ok thanks! Also a noob question: How would I adapt your code to accept a file like [this](https://raw.githubusercontent.com/quantum-package-manager/repo/main/repo/neofetch/quantum.lua) (where it grabs the dependencies from the second variable) Note: I already have made it so it can process everything but the dependency part – RhinoCodes Nov 12 '20 at 23:57
  • 1
    @ChocolateMeteor So instead of taking the table as a parameter, you want to read it from the Lua global called `dependencies`? If so, then replace the first `lua_settop(L, 1);` with `lua_settop(L, 0); lua_getglobal(L, "dependencies");`. – Joseph Sible-Reinstate Monica Nov 13 '20 at 00:34