Passing array to C as argument in the stack

大兔子大兔子 提交于 2019-12-13 01:53:15

问题


I use Lua for arrays manipulating; arrays are simple binary data:

local ram_ctx = {0,0,0,0,0,0,0,0,0}

I want to pass it to GUI written in C. The problem is if I pass it directly like func(ram_ctx), Lua function seems to stop executing after a call. Corresponding C function are not executed (it can be empty). But if I make global array in Lua and access it with lua_getglobal - everything seems to be OK. What I'm doing wrong or is it possible at all? It is not OK to pass array name as argument in order to call it as global array

Lua code:

function device_init()
--set_callback(1000000000000, 0)
local array = {0xFF,0,0,0,0,0,0}
--create_memory_popup("Test")
set_memory_popup(array)
end

Here is C code I try to use:

static int32_t lua_set_popup_memory (lua_State *L) 
{  
  int32_t argnum = lua_gettop(L);
  if (1 != argnum)
  {
    out_error("Function %s expects 1 argument got %d\n", __PRETTY_FUNCTION__, argnum);
    return 0;
  }  
if (0 == lua_istable(L, -1))
{
    out_log("No array found");
    return 0;
}
int32_t a_size = lua_rawlen(L, -1);
uint8_t *buf = calloc(1, a_size);
for (int i=1;;i++)
{    
    lua_rawgeti(L,-1, i);
    if (lua_isnil(L,-1)) 
        break;
    buf[i] = lua_tonumber(L,-1);
    lua_pop(L, 1);
}
set_popup_memory(memory_popup, 0, buf, a_size);
free(buf);
  return 0;  
}

回答1:


I doubt that someone can actually diagnose the problem in question without full example, but here is idiomatic way to handle Lua-to-C calls and some comments on the code itself:

static int // not int32_t
lua_set_popup_memory(lua_State *L)
{
    luaL_checktype(L, 1, LUA_TTABLE);
    // let alone excessive arguments (idiomatic), or do:
    lua_settop(L, 1);

    int a_size = lua_rawlen(L, 1); // absolute indexing for arguments
    uint8_t *buf = malloc((size_t)a_size);

    for (int i = 1; i <= a_size; i++) {
        lua_pushinteger(L, i);
        lua_gettable(L, 1); // always give a chance to metamethods
        // OTOH, metamethods are already broken here with lua_rawlen()
        // if you are on 5.2, use lua_len()

        if (lua_isnil(L, -1)) { // relative indexing for "locals"
            a_size = i-1; // fix actual size (e.g. 4th nil means a_size==3)
            break;
        }

        if (!lua_isnumber(L, -1)) // optional check
            return luaL_error(L, "item %d invalid (number required, got %s)",
                              i, luaL_typename(L, -1));

        lua_Integer b = lua_tointeger(L, -1);

        if (b < 0 || b > UINT8_MAX) // optional
            return luaL_error(L, "item %d out of range", i);

        buf[i-1] = b; // Lua is 1-based, C is 0-based
        lua_pop(L, 1);
    }

    set_popup_memory(memory_popup, 0, buf, a_size);
    free(buf);

    return 0;
}

Please note that lua_CFunction is defined as int (*)(lua_State *), so return type of int32_t may (and most likely will) cause problems on non-32-bit platforms. Also, original code is probably overflowing buf[i], because C indexes start with zero, not 1. And there is one more obvious issue: lua_rawlen() may return the index greater than loop counts to (e.g. array with nil-holes), causing unneeded zeroes being passed to set_popup_memory (assuming priority of first-nil method over table length).

Not sure about out_error, the use of Lua errors may give cleaner diagnostics, especially when entry point was called with lua_pcall's traceback argument.

This code snippet was not actually tested.



来源:https://stackoverflow.com/questions/25940366/passing-array-to-c-as-argument-in-the-stack

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!