c++ - 从 Lua 修改 main() 中的 C++ 数组,无需额外分配

标签 c++ lua luajit luabridge

我正在绘制一个小型 C++ 程序,它将数组传递给 Lua 并在那里对其进行修改,我打算在程序中读取一个 lua 脚本,这样我就可以修改它而无需重新编译程序
我的第一个障碍是确保 Lua 能够修改已经分配的数组,而不是让它们在 Lua 空间中再次分配。数据将是 float 的,大小会非常大,但我现在开始很小。
为了简化这个界面,我尝试了 LuaBridge 2.6,但它没有提供预期的结果。下面是一个完全“工作”的程序。

#include <iostream>
#include <cstdint>
#include <cstring>
#include <vector>
#include <lua5.3/lua.hpp>
#include <LuaBridge/LuaBridge.h>

int main(void)
    {
    const uint32_t      LENGTH = 512 * 256;
    std::vector <float> input(LENGTH),
                        output(LENGTH);

    memset(output.data(), 0, LENGTH * sizeof(float));   // Zero the output
    for(uint32_t i = 0; i < LENGTH; i++)                // Populate input
        input[i] = (float)i + 0.5f;

    lua_State *luastate = luaL_newstate();
    luabridge::push(luastate, input.data());    // Supposedly passing a pointer to the first element of input, according to LuaBridge manual chap 3-3.1
    luabridge::push(luastate, output.data());   // Same for output

    luaL_dostring(luastate, "output[10] = input[256]");     // Expecting to assign this value in the C++ arrays, not in the Lua space
    lua_getglobal(luastate, "output[10]");                  // Find this assigned value in the Lua stack
    lua_Number val = lua_tonumber(luastate, 1);             // Retrieving this value from Lua to C++

    std::cout << input[256] << ", " << output[10] << ", " << val << std::endl;  // The values of val and in output[10] don't match

    lua_close(luastate);

    return 0;
    }
请注意,没有任何匹配项。 Lua 中的 output[10] 不是 C++ 空间中 input[256] 的值,而是 input[0]。
C++ 输出数组没有从 Lua 内部更新,cout 显示它保持我们初始化的状态 (0)。
为了确认这一点,我们将 output[10] 的这个值推送到堆栈中,它不是 C++ 中的 input[256],而是从 C++ 中检索的。
你们能纠正我或指出我应该在哪里实现这一目标吗?
======= 2020 年 8 月 11 日更新 =======
为了澄清程序正在做什么(或应该做什么),在阅读了 Robert 和 Joseph 的考虑之后,我在下面发布了 C++ 部分和它调用的 lua 脚本的更新版本。请注意,我放弃了 LuaBridge,因为我在第一次尝试中没有成功:
C++:
#include <iostream>
#include <cstdint>
#include <cstring>
#include <vector>
#include <luajit-2.0/lua.hpp>  // LuaJIT 2.0.4 from Ubuntu 16.04

int main(void)
    {
    const uint32_t      LENGTH = 256 * 512;
    std::vector <float> input(LENGTH),
                        output(LENGTH);

    memset(output.data(), 0, LENGTH * sizeof(float));
    for(uint32_t i = 0; i < LENGTH; i++)
        input[i] = (float)i + 0.5f;

    lua_State *luastate = luaL_newstate();
    luaL_openlibs(luastate);

    // Here I have to pass &input[0], &output[0] and LENGTH
    // to Lua, which in turn will pass to whatever functions
    // are being called from a .so lib opened in Lua-side

    luaL_dofile(luastate, "my_script.lua");    
    lua_close(luastate);

    return 0;
    }
Lua 脚本如下所示:
local ffi = require("ffi")
local mylib = ffi.load("/path_to_lib/mylib.so")

-- Here I import and call any fuctions needed from mylib.so
-- without needing to recompile anything, just change this script
-- At this point the script has to know &input[0], &output[0] and LENGTH

ffi.cdef[[int func1(const float *in, float *out, const uint32_t LEN);]]
ffi.cdef[[int func2(const float *in, float *out, const uint32_t LEN);]]
ffi.cdef[[int funcX(const float *in, float *out, const uint32_t LEN);]]

if(mylib.func1(input, output, LENGTH) == 0) then
    print("Func1 ran successfuly.")
else
    print("Func1 failed.")
end

最佳答案

I am sketching a small C++ program that will pass arrays to Lua


The data will be float and the size will be really large,


我的建议:
  • 将缓冲区保留在 C 端(例如作为全局变量)
  • 向 LUA 公开 C 函数 GetTableValue(Index)
  • 向 Lua 公开 C 函数 SetTableValue(Index, Value)

  • 它应该是这样的:
    static int LUA_GetTableValue (lua_State *LuaState)
    {
      float Value;
    
      /* lua_gettop returns the number of arguments */
      if ((lua_gettop(LuaState) == 1) && (lua_isinteger(LuaState, -1)))
      {
        /* Get event string to execute (first parameter) */
        Offset = lua_tointeger(LuaState, -1);
    
        /* Get table value */
        Value  = LUA_FloatTable[Offset];
    
        /* Push result to the stack */
        lua_pushnumber(Value);
      }
      else
      {
        lua_pushnil(LuaState);  
      }
    
      /* return 1 value */
      return 1;
    }
    
    您还需要注册该功能:
    lua_register(LuaState, "GetTableValue", LUA_GetTableValue);
    
    我让你写SetTableValue但它应该非常接近。
    这样做,缓冲区在 C 端,可以从 Lua 访问。具有专用功能。

    关于c++ - 从 Lua 修改 main() 中的 C++ 数组,无需额外分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64707309/

    相关文章:

    c++ - 使用指针的 vector 移位

    c++ - 创建可以存储 secret 信息的 C++ 应用程序

    c++ - Qt 生成文件错误

    c++ - 在 main.cpp 中实现 MainWindow 时缺少 vtable

    java - Lua 在 Android 上是否与 Java 一样强大,或者有什么限制?

    c - 使用 C 函数 notify_notification_update() 的段错误

    c - 如何从 C 中读取 Torch 张量

    lua - Torch 和 Lua 是什么关系?

    lua - lua中的堆内存访问

    lua - Lua 的表长度运算符是如何工作的?