Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
简化Lua函数对C函数的调用_Lua - Fatal编程技术网

简化Lua函数对C函数的调用

简化Lua函数对C函数的调用,lua,Lua,我是Lua的新手 我有一个注册到Lua的C函数,如下所示: call(obj, "func", param0, param1) obj.func(param0, param1) 在调用()中: 在C语言中,我们通过自定义反射逻辑来完成一些复杂的函数分派++ obj(和所有参数)都是固定的包装类型(类似于boost::any) 因此,我们不能使用常规的Lua绑定工具(luabind、luabridge等)进行简单的类成员注册 问题是: 我们如何将Lua调用简化为这样: call(obj,

我是Lua的新手

我有一个注册到Lua的C函数,如下所示:

call(obj, "func", param0, param1)
obj.func(param0, param1)
调用()
中:

  • 在C语言中,我们通过自定义反射逻辑来完成一些复杂的函数分派++
  • obj
    (和所有参数)都是固定的包装类型(类似于
    boost::any
因此,我们不能使用常规的Lua绑定工具(luabind、luabridge等)进行简单的类成员注册

问题是:

我们如何将Lua调用简化为这样:

call(obj, "func", param0, param1)
obj.func(param0, param1)

?


谢谢。

您必须在您创建的每个
obj
上设置一个元表(假设它是您控制下的用户数据,并且没有元表),并覆盖其中的
\u index
元方法:

local cache = { }

debug.setmetatable(obj, {
    __index = function (obj, k)
        return function (obj, ...) -- or (...) for [non-canonical] .-syntax
            return call(obj, k, ...)
        end

        -- malloc-optimized version --
        local f = cache[k] or function (obj, ...) return call(obj, k, ...) end
        cache[k] = f
        return f
    end,
    __metatable = "whatever",
})

f = obj.func
f(obj, param0, param1) --> call(obj, 'func', param0, param1)

obj:func(param0, param1) --> the same via syntactic sugar
如果
obj
已经有一个元表,那么必须以类似的方式修改该元表

同样的操作也可以通过C接口完成,因此您可以将
obj
创建与
\u索引
设置相结合


C端更新:

若创建函数位于外部库中,那个么除了捕获所有对象外观点(返回值和作为参数传递的表中的值)并如上所述将其换行外,并没有其他选项

如果创建函数在您的控制下,您可以在那里看到类似的内容:

ud = lua_newuserdata(L, sizeof(object));
*ud = object;

// this part is missing if objects have no metatable at all
luaL_getmetatable(L, tname); // or 'if (luaL_newmetatable(L, tname)) { ... }'
lua_setmetatable(L, -2);

return 1;
必须在创建元表的位置添加_uindex元方法:

…代码中的某个地方,可能就在
*ud=object
行之后

if (luaL_newmetatable(L, tname)) {
    ... original metatable setup ...

    int res = luaL_loadstring(L,
        "return function (obj, k)\n"
        "    return function (obj, ...)\n"
        "        return call(obj, k, ...)\n"
        "    end\n"
        "end\n");
    assert(res == 0);

    lua_call(L, 0, 1);
    lua_setfield(L, -2, "__index");
}
如果您的userdata根本没有元表,则必须创建并设置它

如果您想去掉全局符号
调用
,则将其C实现作为参数传递给luaL_loadstring'ed chunk:

luaL_loadstring(L, "local call = ...\n return function (obj, k)\n" ...);
lua_pushcfunction(L, l_call);
lua_call(L, 1, 1); // instead of (0, 1)

然后,
call
将被本地化到闭包中。

还要注意,此方法在每次调用它时都会围绕
k
创建一个闭包。为了防止在紧循环中出现这种情况,您可以缓存内部函数(
返回函数…
),并从缓存中返回已经看到的
k
s。(为此添加了示例代码)包装器可能会返回任何
call
返回到调用站点的内容。@greatwolf-谢谢!固定的。此修复的注意事项:由于它现在进行尾部调用,任何与级别相关的lua例程(例如带有级别参数的
error
)都应采用级别1,因为匿名函数(obj,…)将被
call
@user3125367替换谢谢!lua版本有效!但是,如何通过C接口实现呢?由于obj是由C函数创建的,因此通过lua@ZSaberLv0-更新为C