Lua与C的交互(2)

来源:互联网 发布:淘宝网服装货源 编辑:程序博客网 时间:2024/06/02 10:56

示例:

//lua_pushcfunction(L,l_sin);//lua_setglobal(L,"mysin");static int l_sin(lua_state *L){    double d = lua_tonumber(L,1);        /*获取参数*/    lua_pushnumber(L,sin(d));            /*压入结果*/    return 1;                            /*结果的数量*/}

1.所有注册到Lua中的函数都具有相同的原型,该原型就是定义在lua.h中的lua_CFunction:typedef int(*lua_CFunction)(lua_State *L),它仅有一个参数,即Lua的状态。它返回一个整数,表示其压入栈中的返回值数量。因此,这个函数无须在压入结果前清空栈。在它返回后,Lua会自动删除栈中结果之下的内容。
2.lua_pushcfunction:Lua使用C的函数前,必须注册这个函数。可以使用lua_pushcfunction来注册,这个函数要求传入一个指向C函数的指针,它会在Lua中创建一个“函数”类型的值,该值就表示这个C函数。当注册完后,这个C函数就具有了与其他Lua函数一样的行为。

示例:返回指定目录下的所有子目录

#include<dirent.h>#include<errno.h>static int l_dir(lua_State *L){    DIR *dir;    struct dirent *entry;    int i;    const char *path = luaL_checkstring(L,1);    /*打开目录*/    dir = opendir(path);    if(dir == NULL)                         /*打开目录错误*/    {        lua_pushnil(L);                     /*返回nil*/        lua_pushstring(L,streeor(errno));   /*以及错误信息*/        return 2;                           /*结果数量*/    }    /*创建结果table*/    lua_newtable(L);    i = 1;    while((entry = readdir(dir)) != NULL)    {        lua_pushnumber(L,i++);             /*压入key*/        lua_pushstring(L,entry->d_name);   /*压入value*/        lua_settable(L,-3);    }    closedir(dir);    return 1;                              /*table已位于栈顶*/}

示例:

static int l_dir(lua_State *L){}static const struct luaL_Reg mylib[] = {    {"dir",l_dir},    {NULL,NULL}           /*结尾*/};int luaopen_mylib(lua_State *L){    luaL_register(L,"mylib",mylib);    return 1;}

1.luaL_register:这个函数接收一些C函数及其名称,并将这些函数注册到一个与模块同名的table中。

数组操作函数:
1.void lua_rawgeti(lua_State *L,int index,int key):index表示table在栈中的位置,key表示元素在table中的位置。
等价于:

lua_pushnumber(L,key);lua_rawget(L,t);

2.void lua_rawseti(lua_State *L,int index,int key):index表示table在栈中的位置,key表示元素在table中的位置。
等价于:

lua_pushnumber(L,key);lua_insert(L,-2);      /*将'key'放到前一个值的下面*/lua_rawset(L,t);

示例:

int l_map(lua_State *L){    int i,n;    /*第一个参数必须是一个table(t)*/    luaL_checktype(L,1,LUA_TTABLE);    /*第二个参数必须是一个函数(f)*/    luaL_checktype(L,2,LUA_TFUNCTION);    n = lua_objlen(L,1); /*获取table的大小*/    for(i = 1; i <=n; i++)    {        lua_pushvalue(L,2);   /*压入f*/        lua_rawgeti(L,1,i);   /*压入t[i]*/        lua_call(L,1,1);      /*调用f(t[i])*/        lua_rawseti(L,1,i);   /*t[i] = 结果*/    }    return 0;                 /*无结果*/}

1.luaL_checktype:函数确保给定参数具有特定类型,否则它会引发一个错误。
2.lua_call函数完成一次无保护的调用,它类似于lua_pcall,不过在发生错误时,它会传播错误,而非返回错误代码。

字符串操作
1.lua_pushlstring(L,s+i,j-i+1):把字符串s的子串(区间为[i,j])传递给Lua.
2.lua_concat:类似于Lua中的”..”操作符。不过它可以同时连接多个字符串,调用lua_concat(L,n)连接(并弹出)栈顶的n个值,然后压入结果。此外,这个函数会将数字转换为字符串,并在需要时调用元方法。
3.const char* lua_pushfstring(lua_State *L,const char *fmt,…):这个函数有点类似于C函数sprintf,它们都会根据一个格式字符串和一些额外的参数来创建一个新字符串。但与sprintf不同的是,无须提供这个新字符串的缓冲。Lua会动态地创建一个足够大的缓冲来存放新字符串,确保不会有缓冲溢出等问题。这个函数会将结果字符串压入栈中,并返回一个指向它的指针。当前这个字符串接受的指示符只有:%%(表示字符%),%s(表示字符串),%d(表示整数),%f(表示Lua中的数字,即双精度浮点数)及%c(接受一个整数,并将其格式化为一个字符)。除此之外,它不接受任何例如宽度或精度选项。

示例:字符串分割

static int l_split(lua_State *L){    const char *s = luaL_checkstring(L,1);    const char *sep = luaL_checkstring(L,2);    const char *e;    int i = 1;    lua_newtable(L);              /*结果*/    /*遍历所有分隔符*/    while((e = strchr(s,*sep)) != NULL)    {        lua_pushlstring(L,s,e-s);            /*压入子串*/        lua_rawseti(L,-2,i++);        s = e + 1;                           /*跳过分隔符*/    }    /*压入最后一个子串*/    lua_pushstring(L,s);    lua_rawseti(L,-2,i);    return 1;                                 /*返回table*/}
原创粉丝点击