博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C 可变长参数运用-----编写Lua的通用调用函数
阅读量:5320 次
发布时间:2019-06-14

本文共 2782 字,大约阅读时间需要 9 分钟。

1.C可变长参数

printf这个使用频繁的C语言函数的参数列表包含一个const char*的描述串,还有一个可变长参数(...) ,如下为printf的函数声明。

int printf(const char * __restrict, ...)

在stdarg.h这个头文件中包含着对可变长参数进行操作的一些宏(x86平台为例): 

#define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) ( ap = (va_list)0 ) 

其中运行va_start(ap, v)可以使得ap指向可变长参数列表的第一个参数的地址。其中v为最后一个固定参数。

va_arg(ap,T)使ap指向可变长参数列表的下一个参数,并且用输入的类型T进行数据强转换,返回一个用户需要的参数值。

va_end(ap),置ap为NULL。

详细的可变长参数解释请参见这个博客:

 

2.C语言对Lua的通用调用函数

1 #include 
2 3 void call_va(const char * func,const char *sig,...) 4 { 5 va_list vl;//定义一个可变长参数指针,无初始值 6 int narg;//可变长参数的数量 7 int nres;//Lua函数返回值的数量 8 9 va_start(vl,sig);//让指针指向可变长参数的第一个参数首地址10 lua_getglobal(L,func);//函数入栈11 12 //---参数入栈13 for(narg=0;*sig;narg++)//遍历参数14 {15 //检查栈中空间16 luaL_checkstack(L,1,"too many arguments");17 18 switch(*sig++)19 {20 //根据参数的约束符,按类型入栈,d-double i-int s-char*21 case 'd':22 lua_pushnumber(L,va_arg(vl,double));23 break;24 case 'i':25 lua_pushinteger(L,va_arg(vl,int));26 break;27 case 's':28 lua_pushstring(L,va_arg(vl,char*));29 break;30 case '>':31 //输入参数结束32 goto endargs;33 default:34 error(L,"invalid option (%c)",*(sig-1));35 }36 }37 //---参数入栈38 endargs:39 nres=strlen(sig);//期望的Lua函数返回值数量40 41 //调用Lua函数42 if(lua_pcall(L,narg,nres,0)!=0)43 {44 error(L,"error calling '%s':%s",func,lua_tostring(L,-1));45 }46 47 //调用之后的返回值检索48 //栈索引从栈顶往下依次是-1,-2,-3,所以第一个结果的栈索引是-nres49 nres=-nres;50 while(*sig)51 {52 //依次得到返回值的类型描述符 *sig53 switch(*sig++)54 {55 case 'd':56 if(!lua_isnumber(L,nres))57 error(L,"wrong result type");58 *va_arg(vl,double*)=lua_tonumber(L,nres);59 break;60 61 case 'i':62 if(!lua_isnumber(L,nres))63 error(L,"wrong result type");64 *va_arg(vl,int*)=lua_tointeger(L,nres);65 break;66 67 case 's':68 if(!lua_isstring(L,nres))69 error(L,"wrong result type");70 *va_arg(vl,const char**)=lua_tostring(L,nres);71 break;72 73 default:74 error(L,"invalid option (%c)",*(sig-1));75 }76 //结果的参数索引+177 nres++;78 }79 va_end(vl);80 81 }

 

这样,如果我们需要调用一个lua函数,只需要如下的调用形式:

call_va("func","dd>ds",x,y,&z,&s); 

表示这个lua函数的函数名为func,接受两个double,返回一个double和一个字符串,'>'表示参数和返回值结果的分割符。

转载于:https://www.cnblogs.com/kyokuhuang/p/4418416.html

你可能感兴趣的文章
2018-2019-2 网络对抗技术 20165301 Exp 8 Web基础
查看>>
nginx 配置路由规则转发配置记录
查看>>
Java静态内部类
查看>>
jquery实现文字向上滚动
查看>>
正在执行的sql
查看>>
CMDB资产采集
查看>>
Linux 常见的trouble shooting故障排错
查看>>
物联网操作系统的概念和特点
查看>>
Hexo站点之域名配置【2】
查看>>
itsdangerous模块
查看>>
C++ 简单字符串加解密(转载)
查看>>
wireshark
查看>>
攻防工具
查看>>
20. 有效的括号
查看>>
公司级平台-IProgram-DAL
查看>>
【编程工具】Sublime Text3 之 Emmet 插件的详细使用的方法
查看>>
TortoiseGit
查看>>
mysql 递归查询父节点 和子节点
查看>>
简单的自我介绍
查看>>
Pamulinawen--IPA--菲律宾伊洛卡诺语
查看>>