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

本文介绍了在选择Lua与C++交互库时,作者倾向于luabrige、lua_tinker和luna的原因,因为它们代码量小且易于学习。文章通过示例展示了如何使用lua_call()调用Lua代码全局函数,并通过C++模板技术简化了类似luabind的复杂性,具有较高的学习价值。
摘要由CSDN通过智能技术生成


在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;				
		else
			return 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);
		else
			return *(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);
		else
			return *(unsigned long long*)lua_touserdata(L, index);
	}

	// pop a value from lua stack
	template<typename T>  
	T pop(lua_State *L)
	{   //利用C++模板,把栈顶返回值读取到C code中
		T t = read<T>(L, -1); 
		//把栈顶弹出
		lua_pop(L, 1);
		//返回值
		return t; 
	}
// call
	template<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_State
	lua_State *L = lua_open();  /* create state */
	//注册标准库
	luaL_openlibs (L);
	//执行sample_1.lua
	luaL_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 + arg2
end



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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值