1.前言
lua通过一个虚拟栈和一组C API函数来与C通信,该虚拟栈主要解决了lua和c中一些差异性问题,比如lua使用自动垃圾收集,C要求显示释放内存,lua使用动态类型,C使用的是静态类型等,下面将会通过一些代码直接演示C Api的一些用法。
2.C API和代码演示
#include<stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#include<lua.h>
#include<lualib.h>
#include<lauxlib.h>
#ifdef __cplusplus
}
#endif
int main()
{
lua_State *L = luaL_newstate();//创建一个lua的虚拟栈
luaL_openlibs(L);//打开lua中的标准库
lua_pushnil(L); //往栈中压如一个nil
lua_pushboolean(L,0);//往栈中压入一个bool值
lua_pushnumber(L,1.0);//往栈中压入一个浮点数
lua_pushinteger(L,2);//往栈中压入一个整数
lua_pushstring(L,"str");//往栈中压入一个/0结尾额字符串
lua_pushlstring(L,"this is a string",16);//往栈中压入一个字符串并指定压入的长度
int hasSpace = lua_checkstack(L,10);//检查栈中是否有10个空间<返回一个整数用来判断>
int isNum = lua_isnumber(L,3);//检查栈中的3位置能否转换为数字
int isString = lua_isstring(L,5);//检查栈中的5位置能否转换为string
int isTable = lua_istable(L,5);//检查栈中的5位置能否转换为table
lua_type(L,1);//返回栈中的1位置的元素的类型<每种类型对应着lua.h中的一个类型常量>
int boolean = lua_toboolean(L,1);//返回栈中的1位置bool值<不通过转换>
lua_Number num = lua_tonumber(L,1);//返回栈中的1位置浮点数<不通过转换>
lua_Integer intNum = lua_tointeger(L,1);//返回栈中的1位置整数<不通过转换>
const char* str = lua_tostring(L,1);//返回栈中的1位置字符串<不通过转换>
size_t objLen = lua_objlen(L,1);//返回栈中的1位置对象的“长度”
lua_typename(L,1);//将栈中1位置的类型编码转成类型名输出
int count = lua_gettop(L);//获取L栈中的元素总数
lua_settop(L,2);//将当前栈的栈顶设置为该栈的2位置,超出的舍弃,不足的补nil
lua_pushvalue(L,1);//将当前栈1位置的值复制一份压入栈顶
lua_remove(L,1);//删除指定位置元素,并将上面的元素下移
lua_insert(L,1);//上移指定位置的之上的所有元素,并在指定位置插入该位置
lua_replace(L,1);//弹出栈顶的值,并将该值设置到指定位置
lua_pop(L,1);//弹出栈顶的n个值,个数用第二个参数指定 <lua_pop的定义>#define lua_pop(L,n) lua_settop(L,-(n)-1)
printf("%d,%d",hasSpace,lua_gettop(L));
getchar();
return 0;
}
上面仅演示了C API函数的基本用法,可以自己改动运行结果后加深印象(当中某些地方是报错的,可以找出来自己修改程序)
3.C API中的错误处理
c中没有c++或者java中那样的异常处理机制,为此lua采用了c中的setjmp机制,这是一种类似于异常处理的机制
当为lua编写库代码时,使用longjmp几乎和使用异常机制一样,lua能捕获到所有错误,但c调用lua时则需要提供一种异常处理机制.
通常lua应用程序是以一种无保护的模式运行的,当发生错误时,由于不是lua调用的因此无法通过设置适当的上下文捕获错误,此时lua会调用一个紧急函数来处理错误,当该紧急函数调用结束后,lua会结束应用程序,我们可以通过lua_atpanic函数类设置该紧急函数。如果不想应用程序结束,第一可以在紧急函数中条用longjmp跳到之前setjmp的位置,第二是让程序在保护模式下运行,使用lua_pcall函数运行lua代码,为保护与lua交互的C代码,我们可以调用lua_cpcal函数,该函数要求传入一个c函数作为参数.lua本身是安全的,但是将c写的库用到lua中就会打破这种安全性,为lua编写的库函数只有一种标准的错误处理方法,当一个c函数检测到一个错误时,就应该调用lua__error函数,该函数会清理lua中需要清理的东西,然后跳转回发起执行的那个lua_pcall,并附上一条错误消息.