luabind-0.9.1在windows、linux下的使用详解及示例

一. 下载

    1. 本篇博客使用的版本为luabind-0.9.1,下载地址:http://download.csdn.net/download/yzf279533105/10109861

二. 编译

    1. luabind-0.9.1在windows下的编译请参考:http://blog.csdn.net/yzf279533105/article/details/77828811

    2. luabind-0.9.1在linux下的编译请参考:http://blog.csdn.net/yzf279533105/article/details/78483160

三. 示例代码下载

    1. windows下示例代码下载地址(环境是win7,VS2008,已编译出exe,下载后可随意修改代码,重新编译,进行测试):

    https://download.csdn.net/download/yzf279533105/10365718

    

    2. linux下示例点下载地址(环境是centos6.8,gcc4.4.7,已编译出可执行程序,下载后可随意修改代码,重新编译,进行测试。根目录下有详细介绍文档,根据文档里面的步骤进行操作,一定可以运行成功):

    http://download.csdn.net/download/yzf279533105/10135089

    

    3. 如有任何疑问,可联系本人QQ:279533105,添加时请注明来自CSDN

四. 使用(这里对C++和lua的各种交互情景都进行了示例测试)

    C++测试代码如下:

#include <iostream>
using namespace std;

#include "Lua_VM.h"
#include "luabind/luabind.hpp"
using namespace luabind;

extern "C"
{
	#include "lua.h"
	#include "lualib.h"
	#include "lauxlib.h"
}

// 要导出到lua中的函数
void greet()
{
	cout<<"hello world"<<endl;
}

// 要导出到lua中的重载函数
int Add(int nNum1, int nNum2)			// int版的Add函数
{
	return nNum1 + nNum2;
}

string Add(string str1, string str2)	// string版的Add函数
{
	return str1 + str2;
}

// 要导出到lua中的枚举
enum enStudentType
{
	enStudentType_Little,			// 小学生
	enStudentType_Middle,			// 初中生
	enStudentType_High,				// 高中生
	enStudentType_Big,				// 大学生
};
	
// 要导出到lua中的类
class CStudent
{
public:
	CStudent(string strName, int nAge, int nScore, string strScore)
	{
		m_strName	= strName;	// 名字
		m_nAge		= nAge;		// 年龄
		m_nScore	= nScore;	// 成绩(整型)
		m_strScore	= strScore;	// 成绩(字符串型)

		m_nID		= 123;		// ID
		m_strNickName="dog";	// 绰号

		m_nPos		= 12;
	}
public:
	enum enStateType
	{
		enStateType_Learn,		// 学习状态
		enStateType_Play,		// 玩耍状态
		enStateType_Sleep,		// 睡觉状态
	};
	
public:

	// 获取名字
	string GetName()
	{
		return m_strName;
	}

	// 获取年龄
	int GetAge()
	{
		return m_nAge;
	}

	// 获取成绩(整型)
	int GetScore(int nNum1, int nNum2)
	{
		return m_nScore;
	}

	// 获取成绩(字符串型)
	string GetScore(string str1, string str2)
	{
		return m_strScore;
	}

public:

	// 设置位置
	void SetPos(int nPos)
	{
		m_nPos = nPos;
	}
	
	// 获取位置
	int GetPos()
	{
		return m_nPos;
	}
public:
	// 下面两个属性导出到lua
	int		m_nID;			// ID
	string  m_strNickName;	// 绰号

private:
	string	m_strName;		// 名字
	int		m_nAge;			// 年龄
	int		m_nScore;		// 成绩(整型)
	string  m_strScore;		// 成绩(字符串型)
	int 	m_nPos;			// 位置
};


// 要导出到lua中的继承类
class CPeople
{
	int sex;				// 性别
};

class CMan : public CPeople
{
	int nBeard;				// 胡须
};

// 导出到lua
int ExportToLua(lua_State* L)
{
	open(L);

	// 导出到lua全局表
	module(L)
	[
		// 把全局函数greet()导出到lua中
		def("greet", &greet),	

		// 导出全局函数greet()也可以这样写
		//LUA_REG_FREE_FUNC(greet),

		// 把两个全局的Add()重载函数导出到lua中
		def("Add",(int		(*) (int, int))			&Add),	
		def("Add",(string	(*) (string, string))	&Add)
		
		// 导出全局变量
		
		// 导出枚举
		//enum_("constants")
		//[
		//	value("enStudentType_Little", 	enStudentType_Little),	// 小学生
		//	value("enStudentType_Middle", 	enStudentType_Middle),	// 初中生
		//	value("enStudentType_High", 	enStudentType_High),	// 高中生
		//	value("enStudentType_Big", 		enStudentType_Big)		// 大学生
		//]
	];

	// 导出类CStudent
	module(L)
	[
		class_<CStudent>("CStudent")					// 导出类名字"CStudent"
			.def(constructor<string,int,int,string>())	// 导出构造函数
			.def("GetName", &CStudent::GetName)			// 导出GetName()函数
			.def("GetAge", &CStudent::GetAge)			// 导出GetAge()函数
			// LUA_REG_MEM_FUNC(CStudent, GetAge)		// 导出GetAge()函数也可以这样写
			
			// 导出类中的重载函数,注意写法
			.def("GetScore", (int		(CStudent::*)	(int, int))			&CStudent::GetScore)
			.def("GetScore", (string	(CStudent::*)	(string, string))	&CStudent::GetScore)

			// 导出类中的属性
			.def_readonly("m_nID",				&CStudent::m_nID)			// 只读的属性
			.def_readwrite("m_strNickName", &CStudent::m_strNickName)		// 可读可写的属性
			
			// 导出类中的属性,另外一种办法
			.property("m_nPos", 			 &CStudent::GetPos, &CStudent::SetPos)	// 导出属性字段m_nPos到lua,用法有点儿类似C#的get,set
			
			// 导出类中的枚举,注意写法
			.enum_("constants")
			[
				value("enStateType_Learn",	CStudent::enStateType_Learn),	// 学习状态
				value("enStateType_Play", 	CStudent::enStateType_Play),	// 玩耍状态
				value("enStateType_Sleep", 	CStudent::enStateType_Sleep)	// 睡觉状态
			]
	];

	// 要导出到lua的继承类
	module(L)
	[
		class_<CPeople>("CPeople"),
		class_<CMan, CPeople>("CMan")	// 标明继承关系,即CMan继承自CPeople
										// 如果不指定类的继承关系, LuaBind 将不能在相关的继承类型间进行隐式类型转换
	];

	return 0;
}

// 访问lua中的函数,变量,table等
void TestLua(lua_State* L)
{
	printf("\n\n----------   C++开始访问lua中的函数,变量,table     ------------\n\n");

	LUA_CODE_BEGIN

	// 访问lua中的add函数	
	int nAddResult = luabind::call_function<int>(L,"add", 2, 3);
	printf("访问lua的全局函数add(),nAddResult = %d\n\n", nAddResult);

	// 访问lua中的整型全局变量
	int nValue = luabind::object_cast<int>(luabind::globals(L)["nGlobalValue"]);
	printf("访问lua的整型全局变量nGlobalValue = %d\n\n", nValue);
	
	// 访问lua中的字符串型全局变量
	string strValue = luabind::object_cast<string>(luabind::globals(L)["strGlobalValue"]);
	printf("访问lua的字符串型全局变量strGlobalValue = %s\n\n", strValue.c_str());
	
	// 访问lua中的table型全局变量
	
	// 先获取该table
	luabind::object tTable = luabind::globals(L)["globalTable"];
	printf("访问lua的table型全局变量globalTable\n");

	// 判断类型是否为table
	if (type(tTable) == LUA_TTABLE)
	{
		// 再获取该table中的字符串型字段
		string strName = luabind::object_cast<string>(tTable["name"]);
		printf("访问lua的table型全局变量globalTable中的字段name = %s\n",strName.c_str());

		// 再获取该table中的整型字段
		int nAge = luabind::object_cast<int>(tTable["age"]);
		printf("访问lua的table型全局变量globalTable中的字段age = %d\n\n",nAge);
	}

	
	// 调用尾调用的lua函数,测试堆栈
	printf("调用lua出错时的堆栈信息\n");
	printf("可以看到打印出了错误信息 attempt to perform arithmetic on global 'notExistVar' <a nil value>\n");
	printf("但未能打印出全部的调用堆栈,因为发生了尾调用,堆栈被清空了");
	luabind::call_function<int>(L,"functionA",12,34);

	LUA_CODE_END_VOID_RETURN // 由于本函数无返回值,所以用无返回值的宏
}



void main()
{
	//////////////////////////////////////////////////////////		C++函数,变量,枚举在lua中的测试		///////////////////////////
	
	// 把指定的C++的函数,类,属性,枚举导出到lua中
	ExportToLua(LUA_VM.pL());
	
	// 在lua中访问这些C++的函数,变量,在test.lua中进行测试
	LUA_VM.do_file("test.lua");
	
	
	/////////////////////////////////////////////////////////		lua函数,变量,table在C++中的测试		////////////////////////////
	TestLua(LUA_VM.pL());

	// 结束
	getchar();
}

特别注意:编译上面的C++代码时需设置宏LUABIND_DYNAMIC_LINK,否则在导出类的属性时会被认为是函数。。。。。

添加预编译宏的方法,如下图所示:

原因见参考:https://stackoverflow.com/questions/14887246/how-to-get-luabind-properties-to-work


lua测试代码如下:

---------------------------------------------------------------    	下里是lua访问C++导出的内容 	----------------------------------------------------------------
-- 调用c++中的全局函数
print("\ncall C++ global function")
greet()

---------------------------------------------------------------------------------------

-- 调用C++中的重载函数
print("\n\ncall C++ Add(int,int) function")
local nResult = Add(11, 88)								-- 调用int版的Add函数
print("nResult = "..nResult)

print("\ncall C++ Add(string,string) function")
local strResult = Add("123", "456")						-- 调用string版的Add函数
print("strResult = "..strResult)

print("\n\ncall C++ enum")
-- 调用C++中的全局枚举
--print("enStudentType_Little = "..enStudentType_Little)

---------------------------------------------------------------------------------------
-- 实例化C++中的类
print("\n\ncreate a C++ class CStudent")
local student = CStudent("xiaoming", 8, 90, "good")

print("\ncall CStudent function")
local nName = student:GetName()							-- 调用类的一般函数
print("nName = "..nName)	

local nAge = student:GetAge()							-- 调用类的一般函数
print("nAge = "..nAge)

print("\ncall CStudent::GetScore(int,int) function")
local nScore = student:GetScore(8,9)					-- 调用类的重载函数int GetScore(int, int)
print("nScore = "..nScore)

print("\ncall CStudent::GetScore(string,string) function")
local strScore = student:GetScore("math","music")		--调用类的重载函数string GetScore(string, string)
print("strScore = "..strScore)
				
print("\ncall CStudent::m_nID readonly property")		
print(type(student.m_nID))		
print(student.m_nID)									-- 访问类的只读属性
--student.m_nID = 456										-- 修改该属性(这行程序会报错,暂时注释掉,如果打开可看到报错信息"property 'm_nID' is read only")
	
print("\ncall CStudent::m_strNickName readwrite property")		
print("student.m_strNickName "..student.m_strNickName)	-- 访问类的可读可写属性
student.m_strNickName = "cat"							-- 修改该属性
print("student.m_strNickName "..student.m_strNickName)	-- 查看修改结果

print("\ncall cstudent::m_npos property")
--print("student.m_npos"..student.m_npos)				-- 这会触发c++的getpos()
--student.m_npos = 34									-- 这会触发c++的setpos()
--print("student.m_npos"..student.m_npos)

print("\ncall CStudent.enStateType_Learn enum")							
print("CStudent.enStateType_Learn enum = "..CStudent.enStateType_Learn)	-- 调用类中的枚举(注意写法,类的枚举属于类,不属于类的实例)
CStudent.enStateType_Learn = 987										-- 尝试修改C++中的枚举
print("CStudent.enStateType_Learn enum = "..CStudent.enStateType_Learn)	-- 再次打印出来,发现这个枚举值真的被修改了,无语。。。。


---------------------------------------------------------------		下面是C++访问lua的内容	 -------------------------------------------------------------------
-- 全局函数
function add(nNum1, nNum2)
	return nNum1 + nNum2
end

-- 整型全局变量
nGlobalValue = 54321

-- 字符串型全局变量
strGlobalValue = "test global value"

-- table型全局变量
globalTable = 
{
	name = "xiaohong",
	age = 6,
}

-- 测试lua出错时打印出调用堆栈
function functionA(nNum)
	return functionB(nNum)
end

function functionB(nNum)
	return functionC(nNum)
end

function functionC(nNum)
	return notExistVar+nNum		-- 访问一个不存在的变量
end


测试结果如下:


猜你喜欢

转载自blog.csdn.net/yzf279533105/article/details/78631034