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


測試結果如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章