Lua 与C/C++ 交互系列:通过C++调用Lua函数(2)

来源:互联网 发布:网络被劫持怎么办 编辑:程序博客网 时间:2024/05/17 06:47


在Lua和C/C++库,lua user org上面有罗列,但是代码量小,代码容易读,容易学习的库很少.要么提供功能少,例如autoToC 仅仅提供struct绑定。luabind 必须使用Boost库,代码量大,增加了学习难点,同时,luabind库本身代码量就多。

在筛选过程中,我选择了luabrige  lua_tinker  以及luna作为学习的选择。


通过lua_call()调用Lua Code函数已经能够实现.在C++中可以通过模板技术,简单方便的实现C++调用Lua Code全局函数。


sample_2.cpp

#include <iostream>using namespace std;extern "C" {#include "lua.h"#include "lauxlib.h"#include "lualib.h"}namespace lua_tinker{//利用C++编译时模板技术,对push()操作进行模板化// push a value to lua stack template<typename T>  void push(lua_State *L, T ret); //对push函数模板进行显示专用化,对char类型进行特殊处理template<>void lua_tinker::push(lua_State *L, char ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, unsigned char ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, short ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, unsigned short ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, long ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, unsigned long ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, int ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, unsigned int ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, float ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, double ret){lua_pushnumber(L, ret);}template<>void lua_tinker::push(lua_State *L, char* ret){lua_pushstring(L, ret);}template<>void lua_tinker::push(lua_State *L, const char* ret){lua_pushstring(L, ret);}template<>void lua_tinker::push(lua_State *L, bool ret){lua_pushboolean(L, ret);}template<>void lua_tinker::push(lua_State *L, long long ret){ *(long long*)lua_newuserdata(L, sizeof(long long)) = ret;lua_pushstring(L, "__s64");lua_gettable(L, LUA_GLOBALSINDEX);lua_setmetatable(L, -2);}template<>void lua_tinker::push(lua_State *L, unsigned long long ret){*(unsigned long long*)lua_newuserdata(L, sizeof(unsigned long long)) = ret;lua_pushstring(L, "__u64");lua_gettable(L, LUA_GLOBALSINDEX);lua_setmetatable(L, -2);}/*---------------------------------------------------------------------------*/ /* read                                                                      */ /*---------------------------------------------------------------------------*/ //对指定堆栈的索引进行读取数据// read a value from lua stack template<typename T>  T read(lua_State *L, int index);template<>char* lua_tinker::read(lua_State *L, int index){return (char*)lua_tostring(L, index);}template<>const char* lua_tinker::read(lua_State *L, int index){return (const char*)lua_tostring(L, index);}template<>char lua_tinker::read(lua_State *L, int index){return (char)lua_tonumber(L, index);}template<>unsigned char lua_tinker::read(lua_State *L, int index){return (unsigned char)lua_tonumber(L, index);}template<>short lua_tinker::read(lua_State *L, int index){return (short)lua_tonumber(L, index);}template<>unsigned short lua_tinker::read(lua_State *L, int index){return (unsigned short)lua_tonumber(L, index);}template<>long lua_tinker::read(lua_State *L, int index){return (long)lua_tonumber(L, index);}template<>unsigned long lua_tinker::read(lua_State *L, int index){return (unsigned long)lua_tonumber(L, index);}template<>int lua_tinker::read(lua_State *L, int index){return (int)lua_tonumber(L, index);}template<>unsigned int lua_tinker::read(lua_State *L, int index){return (unsigned int)lua_tonumber(L, index);}template<>float lua_tinker::read(lua_State *L, int index){return (float)lua_tonumber(L, index);}template<>double lua_tinker::read(lua_State *L, int index){return (double)lua_tonumber(L, index);}template<>bool lua_tinker::read(lua_State *L, int index){if(lua_isboolean(L, index))return lua_toboolean(L, index) != 0;elsereturn lua_tonumber(L, index) != 0;}template<>void lua_tinker::read(lua_State *L, int index){return;}template<>long long lua_tinker::read(lua_State *L, int index){if(lua_isnumber(L,index))return (long long)lua_tonumber(L, index);elsereturn *(long long*)lua_touserdata(L, index);}template<>unsigned long long lua_tinker::read(lua_State *L, int index){if(lua_isnumber(L,index))return (unsigned long long)lua_tonumber(L, index);elsereturn *(unsigned long long*)lua_touserdata(L, index);}// pop a value from lua stacktemplate<typename T>  T pop(lua_State *L){   //利用C++模板,把栈顶返回值读取到C code中T t = read<T>(L, -1); //把栈顶弹出lua_pop(L, 1);//返回值return t; }// calltemplate<typename RVal>RVal call(lua_State* L, const char* name){lua_pushstring(L, name);lua_gettable(L, LUA_GLOBALSINDEX);lua_pcall(L, 0, 1, errfunc);return pop<RVal>(L);}template<typename RVal, typename T1>RVal call(lua_State* L, const char* name, T1 arg){lua_pushstring(L, name);lua_gettable(L, LUA_GLOBALSINDEX);push(L, arg);lua_call(L, 1, 1);return pop<RVal>(L);}//定义对Lua Code 全局函数的调用。有一个返回值,二个参数。template<typename RVal, typename T1, typename T2>RVal call(lua_State* L, const char* name, T1 arg1, T2 arg2){   //把Lua Code 函数名字压入虚拟栈上面lua_pushstring(L, name);//获取_G[name] 函数到虚拟栈顶lua_gettable(L, LUA_GLOBALSINDEX);//利用C++模板,把第一个参数压入虚拟栈push(L, arg1);//把第二个参数压入虚拟栈中push(L, arg2);//调用lua_call()函数,实际调Lua Code函数,并把Lua Code函数结果压入虚拟栈lua_call(L, 2, 1);//返回C Code值return pop<RVal>(L);}template<typename RVal, typename T1, typename T2, typename T3>RVal call(lua_State* L, const char* name, T1 arg1, T2 arg2, T3 arg3){lua_pushstring(L, name);lua_gettable(L, LUA_GLOBALSINDEX);push(L, arg1);push(L, arg2);push(L, arg3);lua_call(L, 3, 1);return pop<RVal>(L);}}int main(int argc, char **argv){ //创建lua_Statelua_State *L = lua_open();  /* create state *///注册标准库luaL_openlibs (L);//执行sample_1.lualuaL_dofile (L, "sample_2.lua");//对Lua Code 函数进行调用int result = lua_tinker::call<int>(L, "lua_func", 3,1);printf("lua_func(3,4) = %d\n", result);lua_close(L);return 1;}


sample_2.lua 如下代码是 定义的Lua Code函数:

--在Lua Code中定义全局函数function lua_func(arg1, arg2)return arg1 + arg2end



以上代码我节选了 lua_tinker的部分代码。lua_tinker作者是一个韩国人。lua_tinker官网. 官网上有Boost 和Luabind显著的英文,其他都是韩文不得而知其意思。

代码还是很简洁的。把luabind 和boost库实现的东西进行简化过。 在通过c++模板实现,具有很高的学习lua和C++进行交换 的价值。

0 0
原创粉丝点击