现在的位置: 首页 > 综合 > 正文

lua和C交互框架

2013年08月27日 ⁄ 综合 ⁄ 共 4567字 ⁄ 字号 评论关闭

1、错误(err_return)的宏定义
#define err_return(num,fmt,args)  /
    do
    {
        printf("[%s:%d]"fmt"/n",__FILE__,__LINE__,##args);return(num);
    } while(0)

-1  是return的返回值,表示有错误;
fmt 是一个字符串,用于打印错误信息;
args表示参数的个数;--这个有疑问,__FILE__,__LINE__,##args 是什么意思?
另外: while(0)是什么意思,什么条件下可以退出?
具体调用实例:err_return(-1,"luaL_newstat() failed",1);

 

补充解释:

//__FILE__    进行编译的源文件名 
//__LINE__    文件当前有的行号(注意:是"当前") 
//__DATE__    文件被编译的日期 
//__TIME__    文件被编译的时间 
##是字符拼接
像这样 
  在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。 eg.ab##cd 就是abcd, m##1 就是m1;

另外: while(0)是什么意思,什么条件下可以退出?

直接退出,0为false

0是false所以只执行一次do就退出了

while()循环进入的条件是,条件为TRUE,因为0是FALSE,所以循环一次就退出;

do~while() 循环执行一次do里面的内容然后退出,如果直接是while()循环,则不会进入循环体;

 

2、在lua中调用C函数:
(1)C中写好lua要调用的函数

//lua中要调用的c函数定义,实现加法
int csum(lua_State* l)    //定义函数,函数参数是lua_State* l,这也是每个lua要调用的C函数的写法;
{
    int a = lua_tointeger(l,1) ;  //lua_tointeger()获得整型返回值,一般是把lua传进去的数值(参数或者全局变量)转换成整形;
    int b = lua_tointeger(l,2) ;  //这里是指第二个参数,被转化成整形;
    lua_pushinteger(l,a+b) ;      //lua_pushinteger()这里是把返回值(a+b)压入栈
    return 1 ;                    //返回值的数量;
}
可见,lua调用C函数,首先是要写好C中的函数的,首先把函数参数转化成想要的类型,然后把返回值表达式压入栈;
(2)C中写好注册函数,一般是下面的两个:
    lua_pushcfunction(l,csum) ;         //注册在lua中使用的c函数
    lua_setglobal(l,"csum") ;           //绑定到lua中的名字csum
也可以使用:
    lua_register(l,"csum",csum);
因为:
    #define    lua_register(L,n,f)    (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))

(3)C调用lua函数
这里分步进行分析:
main函数里面的事情:
1、/* 初始化lua */
lua_State* l = lua_open();
2、/* 载入Lua基本库 */
luaL_openlibs(L);
另:
    lua_State * l = luaL_newstate() ;    //创建lua运行环境
    if ( l == NULL ) 
 {
            err_return(-1,"luaL_newstat() failed",1);
        }
1、2 和 创建lua运行环境的不同;

3、/* 载入脚本 */
luaL_dofile(L, "add.lua");
luaL_dofile 相当于:(luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
当然使用luaL_loadfile 要注意调用 lua_pcall 函数 清空堆栈;

4、/* 调用Lua函数 */

这里就可以调用之前定义好的功能函数;具体功能封装到C的函数中;

5、/* 显示结果 */
printf( "The sum is %d/n", sum );

6、/* 清除Lua */
lua_close(L);

补充上面第四步,分析封装到C函数中的lua函数调用方法:
int luaadd ( int x, int y )
{
 int sum;                    //定义一个变量作为返回值;
 /* 通过名字得到Lua函数 */
 lua_getglobal(L, "add");    //使用lua_getglobal得到全局变量;
 /* 第一个参数 */
 lua_pushnumber(L, x);       //将第一个参数压入栈中;

 /* 第二个参数 */            
 lua_pushnumber(L, y);       //第二个参数压入栈中;

  /* 调用函数,告知有两个参数,一个返回值 */
 lua_pcall(L, 2, 1,0);      //调用此函数会自动将参数弹出栈,只保留返回值;

 /* 得到结果 */
 sum = (int)lua_tointeger(L, -1);
 lua_pop(L, 1);              //将返回值从栈中清除;   

 return sum;
}
(4)C调用lua全局变量
main函数里面的初始化一样;
另外调用全局变量用的也是lua_getglobal()方法;
比如:lua_getglobal(l,"width");    //获取lua中定义的变量


各种交互具体代码示例:

extern "C"
{
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}

#define err_exit(num,fmt,args)  /
    do{printf("[%s:%d]"fmt"/n",__FILE__,__LINE__,##args);exit(num);} while(0)
#define err_return(num,fmt,args)  /
    do{printf("[%s:%d]"fmt"/n",__FILE__,__LINE__,##args);return(num);} while(0)

//lua中调用的c函数定义,实现加法
int csum(lua_State* l)
{
    int a = lua_tointeger(l,1) ;
    int b = lua_tointeger(l,2) ;
    lua_pushinteger(l,a+b) ;
    return 1 ;
}

int main(int argc,char** argv)
{
    lua_State * l = luaL_newstate() ;        //创建lua运行环境
    if ( l == NULL ) 
 {
  err_return(-1,"luaL_newstat() failed",1);
    }
 //int ret = 0 ;
    int ret = luaL_loadfile(l,"func.lua") ;      //加载lua脚本文件
    if ( ret != 0 ) 
  err_return(-1,"luaL_loadfile failed",1) ;
    ret = lua_pcall(l,0,0,0) ;
    if ( ret != 0 )
  err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;

    lua_getglobal(l,"width");              //获取lua中定义的变量
    lua_getglobal(l,"height");             //如果改变了字符串的值,则不会打印出正确的结果,默认值是0
    printf("height:%ld width:%ld/n",lua_tointeger(l,-1),lua_tointeger(l,-2)) ;
 int n = lua_gettop(l);                 //要声明变量等于lua_gettop()
    lua_pop(l,1) ;                        //恢复lua的栈

    int a = 11 ;
    int b = 12 ;
    lua_getglobal(l,"sum");               //调用lua中的函数sum
    lua_pushinteger(l,a) ;
    lua_pushinteger(l,b) ;
    int m = lua_gettop(l);
    ret = lua_pcall(l,2,1,0) ;
    //if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;
    printf("sum:%d + %d = %ld/n",a,b,lua_tointeger(l,-1)) ;
    lua_pop(l,1) ;

    const char str1[] = "hello" ;
    const char str2[] = "world" ;
    lua_getglobal(l,"mystrcat");          //调用lua中的函数mystrcat
    lua_pushstring(l,str1) ;
    lua_pushstring(l,str2) ;
    ret = lua_pcall(l,2,1,0) ;
   // if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;
    printf("mystrcat:%s%s = %s/n",str1,str2,lua_tostring(l,-1)) ;
    lua_pop(l,1) ;

    //lua_pushcfunction(l,csum) ;         //注册在lua中使用的c函数
    //lua_setglobal(l,"csum") ;           //绑定到lua中的名字csum
 lua_register(l,"csum",csum);

    lua_getglobal(l,"mysum");           //调用lua中的mysum函数,该函数调用本程序中定义的csum函数实现加法
    lua_pushinteger(l,a) ;
    lua_pushinteger(l,b) ;
    ret = lua_pcall(l,2,1,0) ;
    //if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ;
    printf("mysum:%d + %d = %ld/n",a,b,lua_tointeger(l,-1)) ;
    lua_pop(l,1) ;

    lua_close(l) ;                     //释放lua运行环境
    return 0 ;
}

抱歉!评论已关闭.