让 SWIG 生成的 Lua 包装器允许可变参数函数的额外参数
2018-6-4 17:40:34
收藏:0
阅读:119
评论:1
当我使用 SWIG 生成可变参数函数的包装器时,它会插入检查传递给函数的精确参数数量的代码,例如:
%inline %{
void foobar(const char *fmt, ...) {}
生成的包装器总是插入以下内容:
SWIG_check_num_args("foobar",1,1)
如何解决这个问题并允许大于或等于 1 的任意数量的参数?
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

可以通过一系列的hack方法绕过这个问题,并生成当传递额外参数时不会产生错误的代码。
本质上,这些hack方法可以归结为一种观察结果——在
SWIG_check_num_args调用之前,我们只能控制本地变量的声明和初始化。然而,我们可以利用这一点来制作一个本地变量,阴影一个全局变量,并根据此更改行为。%module test %runtime%{ static inline int SWIG_check_num_args_real(lua_State* L, const char *fn, int min_args, int max_args) { SWIG_check_num_args(fn, min_args, max_args); return 1; fail: return 0; } #undef SWIG_check_num_args #define SWIG_check_num_args(name,a,b) if (!SWIG_check_num_args_real(L,name,a,_global_is_varargs?1024:b)) goto fail; static const int _global_is_varargs=0; %} %typemap(in)(const char *fmt,...)(const int _global_is_varargs = 1)%{ $typemap(in,const char *)//默认的字符串东西 //TODO:在这里处理其余的参数 %} %inline%{ void foobar(const char *fmt,...) {} void boring(int i) {} %}为了让这个概念可行,我们需要插入一些代码,用我们可以控制的内容替换默认的宏
SWIG_check_num_args,最好不要完全重新编写宏,以防它稍后发生变化。为此,我们设置一个内联函数,以便我们可以有另一个fail标签供宏使用,但可以在以后的#undef前应用原始定义的宏。有了这个内联函数,我们就可以将宏重新定义为一个稍微更可取的宏,它使用一个名为
_global_is_varargs的变量来动态修改宏的第三个参数,并在我们处于变量参数的情况下将其增加。 (1024是完全任意的,INT_MAX或一些特定实现的限制同样适用)。我们计划遮盖的变量需要以魔术前缀
_global_开始,以避免自动附加后缀到局部变量名称 (http://www.swig.org/Doc3.0/Typemaps.html#Typemaps_nn23)。由于一切都是const,聪明的编译器可能会在不增加额外运行时开销的情况下执行此操作。然后,我们可以编写typemaps来实际创建一个本地变量来遮蔽全局变量,并对Lua参数执行一些实际工作。在我的示例中,我将其作为多参数typemap,但可能不是必需的。(我喜欢确切的匹配方式)。
有了这个,我们可以像预期的那样调用函数(虽然它没有做任何有用的事情,这是预处理器/ FFI/ ABI/ gcc扩展有趣的练习):
Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio > m=require('test') > m.boring() stdin:1: Error in boring expected 1..1 args, got 0 stack traceback: [C]: in function 'test.boring' stdin:1: in main chunk [C]: in ? > m.boring(1) > m.foobar() stdin:1: Error in foobar expected 1..1024 args, got 0 stack traceback: [C]: in function 'test.foobar' stdin:1: in main chunk [C]: in ? > m.foobar('') > m.foobar('',1) > m.foobar('',1,2,3)