将数组作为参数传递给C [英] Passing array to C as argument in the stack

查看:123
本文介绍了将数组作为参数传递给C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Lua进行数组操作;数组是简单的二进制数据:

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

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

我想将其传递给用C编写的GUI. 问题是,如果我像func(ram_ctx)一样直接传递它,Lua函数似乎在调用后停止执行.相应的C函数未执行(可以为空). 但是,如果我在Lua中创建全局数组并使用lua_getglobal访问它,一切似乎都可以. 我做错了还是有可能吗?不能将数组名称作为参数传递,以将其称为全局数组

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代码:

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

这是我尝试使用的C代码:

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

推荐答案

我怀疑有人可以在没有完整示例的情况下实际诊断出问题,但这是处理Lua-to-C调用的惯用方式,并且对代码本身:

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

请注意,lua_CFunction被定义为int (*)(lua_State *),因此int32_t的返回类型可能(很可能会)在非32位平台上引起问题.另外,原始代码可能会溢出buf[i],因为C索引以零而不是1开头.还有一个更明显的问题:lua_rawlen()可能会将大于循环计数的索引返回给(例如,具有零孔的数组),导致不必要的零被传递给set_popup_memory(假设first-nil方法的优先级超过表的长度).

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).

不确定out_error,使用Lua错误可能会提供更清晰的诊断,尤其是当使用lua_pcall的traceback参数调用入口点时.

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.

这篇关于将数组作为参数传递给C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆