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