您可以从lua修改C结构吗?

哭泣的

我希望能够有以下Lua代码:

function myfunc(s)
    print(s.value)
    s.value = 7
end

它应该与此C(++)代码一起工作:

struct MyStruct {
    float value;
};

void func() {
    MyStruct var;
    var.value = 5;

    lua_getglobal(L, "myfunc");
    // push `var` to lua, somehow

    lua_call(L, 1, 0); // prints "5"

    // now, var.value is 7
    assert(var.value == 7);
}

我将如何推入var堆栈,以便lua代码可以修改其变量?

约瑟夫·西布尔-恢复莫妮卡

Standard Lua没有内置的方法可以struct通过表公开s的内容,因此这样做是手动过程。这是一个完整程序的示例,可以满足您的需求:

#include <assert.h>
#include <string.h>

#include <lua5.3/lua.h>
#include <lua5.3/lualib.h>
#include <lua5.3/lauxlib.h>

struct MyStruct {
    float value;
};

int MyStruct_index(lua_State *L) {
    struct MyStruct *t = (struct MyStruct *)luaL_checkudata(L, 1, "MyStruct");
    const char *k = luaL_checkstring(L, 2);
    if(!strcmp(k, "value")) {
        lua_pushnumber(L, t->value);
    } else {
        lua_pushnil(L);
    }
    return 1;
}

int MyStruct_newindex(lua_State *L) {
    struct MyStruct *t = (struct MyStruct *)luaL_checkudata(L, 1, "MyStruct");
    const char *k = luaL_checkstring(L, 2);
    if(!strcmp(k, "value")) {
        t->value = luaL_checknumber(L, 3);
        return 0;
    } else {
        return luaL_argerror(L, 2,
                             lua_pushfstring(L, "invalid option '%s'", k));
    }
}

struct MyStruct *MyStruct_new(lua_State *L) {
    struct MyStruct *var = (struct MyStruct *)lua_newuserdata(L, sizeof *var);
    luaL_setmetatable(L, "MyStruct");
    return var;
}

void func(lua_State *L) {
    // Since this is allocated inside of Lua, it will be garbage collected,
    // so we don't need to worry about freeing it
    struct MyStruct *var = MyStruct_new(L);
    var->value = 5;

    lua_getglobal(L, "myfunc");
    lua_pushvalue(L, -2); // push `var` to lua, somehow

    lua_call(L, 1, 0); // prints "5"

    // now, var->value is 7
    assert(var->value == 7);
}

int main(void) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    // One-time setup that needs to happen before you first call MyStruct_new
    luaL_newmetatable(L, "MyStruct");
    lua_pushcfunction(L, MyStruct_index);
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, MyStruct_newindex);
    lua_setfield(L, -2, "__newindex");
    lua_pop(L, 1);

    luaL_dostring(L, "function myfunc(s) print(s.value) s.value = 7 end");
    func(L);

    lua_close(L);
    return 0;
}

要支持更多字段,您必须将其添加到MyStruct_index和中MyStruct_newindex如果要pairs进行处理,则还需要添加一种__pairs元方法。通常,尽管如此,通常更喜欢公开getter和setter方法。

如果您想struct MyStruct在Lua之外分配您的位置,则可以在使用它的任何地方添加一个额外的间接层,如下所示:

#include <assert.h>
#include <string.h>

#include <lua5.3/lua.h>
#include <lua5.3/lualib.h>
#include <lua5.3/lauxlib.h>

struct MyStruct {
    float value;
};

int MyStruct_index(lua_State *L) {
    struct MyStruct **t = (struct MyStruct **)luaL_checkudata(L, 1, "MyStruct");
    const char *k = luaL_checkstring(L, 2);
    if(!strcmp(k, "value")) {
        lua_pushnumber(L, (*t)->value);
    } else {
        lua_pushnil(L);
    }
    return 1;
}

int MyStruct_newindex(lua_State *L) {
    struct MyStruct **t = (struct MyStruct **)luaL_checkudata(L, 1, "MyStruct");
    const char *k = luaL_checkstring(L, 2);
    if(!strcmp(k, "value")) {
        (*t)->value = luaL_checknumber(L, 3);
        return 0;
    } else {
        return luaL_argerror(L, 2,
                             lua_pushfstring(L, "invalid option '%s'", k));
    }
}

void MyStruct_push(lua_State *L, struct MyStruct *var) {
    struct MyStruct **t = (struct MyStruct **)lua_newuserdata(L, sizeof *t);
    *t = var;
    luaL_setmetatable(L, "MyStruct");
}

void func(lua_State *L) {
    struct MyStruct var;
    var.value = 5;

    lua_getglobal(L, "myfunc");
    MyStruct_push(L, &var); // push `var` to lua, somehow

    lua_call(L, 1, 0); // prints "5"

    // now, var.value is 7
    assert(var.value == 7);

    // WARNING! `var` is about to go out of scope! If Lua uses the userdata
    // that references it beyond this point, it's Undefined Behavior! Make
    // sure that it didn't keep a copy of it!
}

int main(void) {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    // One-time setup that needs to happen before you first call MyStruct_new
    luaL_newmetatable(L, "MyStruct");
    lua_pushcfunction(L, MyStruct_index);
    lua_setfield(L, -2, "__index");
    lua_pushcfunction(L, MyStruct_newindex);
    lua_setfield(L, -2, "__newindex");
    lua_pop(L, 1);

    luaL_dostring(L, "function myfunc(s) print(s.value) s.value = 7 end");
    func(L);

    lua_close(L);
    return 0;
}

但这很危险!如果Lua用户数据的寿命超过了它所指向的对象,则将导致未定义行为!

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

您可以在C语言中的main中将变量声明为结构吗?

来自分类Dev

您可以通过编程方式修改UICollectionView scrollDirection吗?

来自分类Dev

在Java中,您可以在遍历列表时修改它吗?

来自分类Dev

您可以修改通过#await获得的结果吗?

来自分类Dev

您可以通过编程方式修改UICollectionView scrollDirection吗?

来自分类Dev

您可以从Powershell中的PostCommandLookupAction访问/修改参数吗?

来自分类Dev

在Lua中,您可以从'self'获得对象名称吗?

来自分类Dev

您可以在redis中查看lua脚本吗?

来自分类Dev

您可以为多种类型实现通用结构吗?

来自分类Dev

您可以控制借用结构还是借用字段吗?

来自分类Dev

打字稿:您可以基于层次结构创建类型吗?

来自分类Dev

您可以将函数参数结构传递给函数吗?

来自分类Dev

AngularJS-您可以在不修改其核心源的情况下重命名服务吗?

来自分类Dev

您可以在Linux系统上隐藏文件夹的“修改日期”时间吗?

来自分类Dev

您可以使用VQMOD直接修改bootstrap.min.css吗?

来自分类Dev

您可以在一个语句中修改多个对象吗?

来自分类Dev

您可以通过发布任务修改SBT构建的名称和版本吗?

来自分类Dev

您可以在创建 JWT 令牌后(加密和签名后)修改其标头吗?

来自分类Dev

您可以解释此C ++函数定义的语法吗?

来自分类Dev

您可以在Redis c#中检索TTL吗?

来自分类Dev

您可以在C ++中使用Java Swing吗

来自分类Dev

您可以在C ++中定义同义词吗?

来自分类Dev

您可以确定C中的堆栈深度吗?

来自分类Dev

您可以从iOS C插件“当场”写入Unity纹理吗?

来自分类Dev

您可以在Linux终端中编译并运行c ++文件吗?

来自分类Dev

您可以解释此C ++函数定义的语法吗?

来自分类Dev

您可以在C中使函数参数指向变量吗?

来自分类Dev

在C ++中,您可以让类成员成为传入的引用吗?

来自分类Dev

您可以在c中的函数的callong中调用函数吗

Related 相关文章

  1. 1

    您可以在C语言中的main中将变量声明为结构吗?

  2. 2

    您可以通过编程方式修改UICollectionView scrollDirection吗?

  3. 3

    在Java中,您可以在遍历列表时修改它吗?

  4. 4

    您可以修改通过#await获得的结果吗?

  5. 5

    您可以通过编程方式修改UICollectionView scrollDirection吗?

  6. 6

    您可以从Powershell中的PostCommandLookupAction访问/修改参数吗?

  7. 7

    在Lua中,您可以从'self'获得对象名称吗?

  8. 8

    您可以在redis中查看lua脚本吗?

  9. 9

    您可以为多种类型实现通用结构吗?

  10. 10

    您可以控制借用结构还是借用字段吗?

  11. 11

    打字稿:您可以基于层次结构创建类型吗?

  12. 12

    您可以将函数参数结构传递给函数吗?

  13. 13

    AngularJS-您可以在不修改其核心源的情况下重命名服务吗?

  14. 14

    您可以在Linux系统上隐藏文件夹的“修改日期”时间吗?

  15. 15

    您可以使用VQMOD直接修改bootstrap.min.css吗?

  16. 16

    您可以在一个语句中修改多个对象吗?

  17. 17

    您可以通过发布任务修改SBT构建的名称和版本吗?

  18. 18

    您可以在创建 JWT 令牌后(加密和签名后)修改其标头吗?

  19. 19

    您可以解释此C ++函数定义的语法吗?

  20. 20

    您可以在Redis c#中检索TTL吗?

  21. 21

    您可以在C ++中使用Java Swing吗

  22. 22

    您可以在C ++中定义同义词吗?

  23. 23

    您可以确定C中的堆栈深度吗?

  24. 24

    您可以从iOS C插件“当场”写入Unity纹理吗?

  25. 25

    您可以在Linux终端中编译并运行c ++文件吗?

  26. 26

    您可以解释此C ++函数定义的语法吗?

  27. 27

    您可以在C中使函数参数指向变量吗?

  28. 28

    在C ++中,您可以让类成员成为传入的引用吗?

  29. 29

    您可以在c中的函数的callong中调用函数吗

热门标签

归档