如何使用作为参数传递给一个lua C函数传递表工作? [英] How to work with tables passed as an argument to a lua C function?

查看:159
本文介绍了如何使用作为参数传递给一个lua C函数传递表工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要实现与C语言的函数,将由Lua的脚本调用。

这个功能应该得到一个Lua表作为参数,所以我应该读取table.I领域尝试做如下图所示,但是当我运行我的功能崩溃。谁能帮我找到了问题?



/ *
 功能findImage(选项)
    的ImagePath = options.imagePath
    模糊= options.fuzzy
    ignoreColor = options.ignoreColor;
 结束 调用示例:  findImage {=的ImagePath的/ var / image.png,模糊= 0.5,ignoreColor = 0XFFFFFF} * /
//实现用C语言函数
静态INT findImgProxy(lua_State * L)
{
    luaL_checktype(L,1,LUA_TTABLE);    lua_getfield(L,-1,的ImagePath);
    如果(!lua_isstring(L,-1)){
        错误();
    }
    为const char *的ImagePath = lua_tostring(L,-2);
    调用lua_pop(L,1);    lua_getfield(L,-1,模糊);
    如果(!lua_isnumber(L,-1)){
        错误();
    }
    浮模糊= lua_tonumber(L,-2);    lua_getfield(L,-1,ignoreColor);
    如果(!lua_isnumber(L,-2)){
        错误();
    }
    浮ignoreColor = lua_tonumber(L,-2);    ...    返回1;
}

如何从C返回表到Lua:



结构点{
    INT X,Y;
}
的typedef点点;
静态INT returnImageProxy(lua_State * L)
{
    点点[3] = {{11,12},{21,22},{31,32}};    lua_newtable(L);    的for(int i = 0;我3;我++){
        lua_newtable(L);
        调用lua_pushnumber(L,点[I] .X);
        lua_rawseti(L,-2,0);
        调用lua_pushnumber(L,点[I] .Y);
        lua_rawseti(L,-2,1);
        lua_settable(L,-3);
    }    返回1; //我要回一个Lua表所示:{{11,12},{21,22},{31,32}}
}


解决方案

在使用Lua的C API工作它来获得舒适的虚拟堆叠的工作是很重要的 - 所有重要的语言边界的相互作用发生在那里。看着你code片段,它看起来并不像你在正确的编组数据为C。

在写一个lua的C函数,你基本上做3件事情:


  • 转换输入数据卢阿到的东西,你可以在C一起工作。

  • 执行处理或任何功能需要做。

  • 转换并返回如有回卢阿输出结果。

作为一个例子,这里是你的 findImgProxy 应该是这样的:

 静态INT findImgProxy(lua_State * L)
{
  //丢弃传入任何额外的参数
  lua_settop(L,1);
  luaL_checktype(L,1,LUA_TTABLE);  //我们获取数据的表
  //'解包'通过将值搬上了台面
  //堆栈第一。然后转换这些堆栈值
  //为一个适当的C型。
  lua_getfield(L,1的ImagePath);
  lua_getfield(L,1,模糊);
  lua_getfield(L,1,ignoreColor);
  //堆栈现在有以下几点:
  // 1 = {=的ImagePath的/ var / image.png,模糊= 0.5,ignoreColor = 0XFFFFFF}
  // -3 =/var/image.png
  // -2 = 0.5
  // -1 = 0XFFFFFF  为const char *的ImagePath = luaL_checkstring(L,-3);
  双模糊= luaL_checknumber(L,-2);
  INT ignoreColor = luaL_checkint(L,-1);
  //我们可以弹出模糊ignoreColor从堆栈
  //因为我们通过价值得到了他们
  调用lua_pop(L,2);  //做处理功能
  // ...  返回1;
}

请注意,我们必须保持的ImagePath 在堆栈上,因为我们持有为const char * 它。弹出该字符串将关闭无效 *的ImagePath 自卢阿可以收集它。

另外,你可以通过复制 luaL_checkstring 返回到另一个缓冲区中的字符串。在这种情况下,突然出现的串关是确定的,因为我们不再指向由LUA拥有内部缓冲区。

编辑:如果有的在表中的键都是可选的,你可以使用 luaL_opt * 功能,而不是提供的默认值。例如,如果模糊 ignoreColor 是可选的:

  // ...
  为const char *的ImagePath = luaL_checkstring(L,-3);
  双模糊= luaL_optnumber(L,-2,0.0); //默认为0.0,如果没有模糊
  INT ignoreColor = luaL_optint(L,-1,0); //默认为0,如果没有ignoreColor
  // ...

因此​​,如果调用code提供了一个关键的一个无意义的值,这仍然会产生一个错误。 OTOH,如果它不存在则该值为并提供了使用默认值。

I'm going to implement a function with C language and which will be called by Lua script.

This function should receive a lua table as the argument, so I should read the fields in the table.I try to do like below, but my function is crashing when I run it. Can anyone help my find the problem?


/*
 function findImage(options)
    imagePath = options.imagePath
    fuzzy = options.fuzzy
    ignoreColor = options.ignoreColor;


 end

 Call Example:

  findImage {imagePath="/var/image.png", fuzzy=0.5, ignoreColor=0xffffff}

 */


// implement the function by C language
static int findImgProxy(lua_State *L)
{
    luaL_checktype(L, 1, LUA_TTABLE);

    lua_getfield(L, -1, "imagePath");
    if (!lua_isstring(L, -1)) {
        error();
    }
    const char * imagePath = lua_tostring(L, -2);
    lua_pop(L, 1);

    lua_getfield(L, -1, "fuzzy");
    if (!lua_isnumber(L, -1)) {
        error();
    }
    float fuzzy = lua_tonumber(L, -2);

    lua_getfield(L, -1, "ignoreColor");
    if (!lua_isnumber(L, -2)) {
        error();
    }
    float ignoreColor = lua_tonumber(L, -2);

    ...

    return 1;
}

How about return a table from C to Lua:


struct Point {
    int x, y;
}
typedef Point Point;


static int returnImageProxy(lua_State *L)
{
    Point points[3] = {{11, 12}, {21, 22}, {31, 32}};

    lua_newtable(L);

    for (int i = 0; i  3; i++) {
        lua_newtable(L);
        lua_pushnumber(L, points[i].x);
        lua_rawseti(L, -2, 0);
        lua_pushnumber(L, points[i].y);
        lua_rawseti(L, -2, 1);
        lua_settable(L,-3);
    }

    return 1;   // I want to return a Lua table like :{{11, 12}, {21, 22}, {31, 32}}
}

解决方案

When working with the Lua C API it's important to get comfortable working with the virtual stack -- all the important language boundary interactions happen there. Looking at your code snippet, it does not look like you're marshaling the data properly over to C.

When writing a lua C function you basically have to do 3 things:

  • Convert input lua data into something you can work with in C.
  • Perform the processing or whatever the function needs to do.
  • Convert and return the output result if any back to lua.

As an example, here's what your findImgProxy should look like:

static int findImgProxy(lua_State *L)
{
  // discard any extra arguments passed in
  lua_settop(L, 1);
  luaL_checktype(L, 1, LUA_TTABLE);

  // Now to get the data out of the table
  // 'unpack' the table by putting the values onto
  // the stack first. Then convert those stack values
  // into an appropriate C type.
  lua_getfield(L, 1, "imagePath");
  lua_getfield(L, 1, "fuzzy");
  lua_getfield(L, 1, "ignoreColor");
  // stack now has following:
  //   1  = {imagePath="/var/image.png", fuzzy=0.5, ignoreColor=0xffffff}
  //   -3 = "/var/image.png"
  //   -2 = 0.5
  //   -1 = 0xffffff

  const char *imagePath = luaL_checkstring(L, -3);
  double fuzzy    = luaL_checknumber(L, -2);
  int ignoreColor = luaL_checkint(L, -1);
  // we can pop fuzzy and ignoreColor off the stack
  // since we got them by value
  lua_pop(L, 2);

  // do function processing
  // ...

  return 1;
}

Note that we must keep imagePath on the stack since we're holding a const char * to it. Popping that string off would invalidate *imagePath since lua might collect it.

Alternatively, you can copy the string returned by luaL_checkstring into another buffer. Popping the string off in this case is ok since we're no longer pointing to an internal buffer owned by lua.

Edit: If some of the keys in the table are optional, you can use the luaL_opt* functions instead and provide defaults. For example, if fuzzy and ignoreColor are optional:

  // ...
  const char *imagePath = luaL_checkstring(L, -3);
  double fuzzy    = luaL_optnumber(L, -2, 0.0); // defaults to 0.0 if no fuzzy
  int ignoreColor = luaL_optint(L, -1, 0);      // defaults to 0 if no ignoreColor
  // ...

So if the calling code provides a nonsensical value for a key, this will still raise an error. OTOH, if it's absent then the value is nil and the default provided is used instead.

这篇关于如何使用作为参数传递给一个lua C函数传递表工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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