运用模版手段向lua中注入c函数

本文介绍了如何使用模板技术在Lua中注册和调用C函数,避免了将每个C函数修改为lua_CFunction类型的需要。通过代理C函数和lightuserdata,实现了C函数的注入,并通过模板推导保持了类型安全。详细讨论了代理函数、参数传递和返回值处理的过程。
摘要由CSDN通过智能技术生成

在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值