一. 下載
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