在lua中使用c函数 需要预先进行注册 ,lua只接受 lua_CFuntion 类型 (lua.h中的定义typedef int (*lua_CFunction) (lua_State *L) ).返回值为函数实际返回的返回值个数,lua与c的交互式通过lua stack进行,通过lua CAPI 在lua和c中进行参数传递.
//ex1 注册c函数到lua中
int fun(lua_State* l)
{
//do some thind
return 0; //返回0个值
}
//将fun注册到lua中去
lua_register(l,"fun",&fun);
//lua中的调用
fun()
lua_register 做两步工作 lua_pushcfunction 和lua_setglobal
lua_pushcfuntion 即 lua_pushcclousre 并且 upvalue 为0
同时使用lua_setglobal 将 lua中 的全局变量 fun指向刚才压入的c闭包
问题: 每一个与lua交互的c函数 必须改为lua_CFuntion 类型
解决方案:
1.使用一个代理c函数来作为与lua的交互 真正的c函数指针 以lightuserdata的形式压入堆栈 并作为代理函数的一个upvalue存在
//用代码说明
//将全局函数注入lua
template<typename Func> //此处的Func为c函数的型别
void def(lua_State* l,char* name,Func func)
{
//压入函数名字 作为global table的key
lua_pushstring(l,name);
lua_pushlightuserdata(l,func);
push_functor(l,func); //此处让编译器进行template 匹配
lua_settable(l,LUA_GLOBALSINDEX);
}
//负责压c函数 无参版本
template <typename RVal>
void push_functor(lua_State* l,RVal (*)())
{
//代理函数为functor::invoke 一个static函数
lua_pushcclosure(l,functor<void>::invoke<RVal>,1);//此处的1为一个upvalue 指先前压入的函数指针
}
//仿造可写出一参版本
template <typename RVal,typename Arg1>
void push_functor(lua_State* l,RVal (*)(Arg1))
//无参调用的c函数
template<>
struct functor<void>
{
//functor中的invoek函数 为宿主程序在lua中的代理
//lua只能注册 luaCFunction类型 int (*func)(lua_State* l)
template<typename RVal>
static int invoke(lua_State* l)
{
//将以upvalue保存的函数指针拿出来执行
//push c函数的返回值到lua stack
push(l,upvalue<RVal (*)()>(l) ());
return 1;
}
//特化版本 函数无返回
template<>
static int invoke<void>(lua_State* l)
{
//无返回的
upvalue<void (*)()>(l)();
return 0;
}
};
//以制定类型读取upvalue值
template <typename T>
T upvalue(lua_State* l)
{
return read<T>(l,lua_upvalueindex(1));//c函数指针在upvalueindex 1处
}
//泛化版本的read函数
//在指定索引处读取lua stack中的函数
template <typename T>
T read(lu