首页 > 系统相关 >luabind-0.9.1在windows、linux下的使用详解及示例

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

时间:2022-12-14 11:38:01浏览次数:81  
标签:0.9 string lua windows 示例 导出 int print CStudent


一. 下载

    1. 本篇博客使用的版本为luabind-0.9.1

二. 编译

    1. luabind-0.9.1在window

 

三. 示例代码下载:

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


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



    4. 2019-04-30有更新,新增加:

        (1) C++结构体导出lua

        (2) 参数为对象指针的函数导出到lua

        本博客下面的代码同步了更新,但下载的示例代码并未更新,望周知

四. 使用(这里对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中的结构体
struct SScore{
string name; // 名字
int score; // 分数
};

// 要导出到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_score.name = "match"; // 成绩:数学
m_score.score = 100; // 成绩:数学,100分

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; // 绰号
SScore m_score; // 成绩
private:
string m_strName; // 名字
int m_nAge; // 年龄
int m_nScore; // 成绩(整型)
string m_strScore; // 成绩(字符串型)
int m_nPos; // 位置
};


// 要导出到lua中的全局函数,参数为对象指针
string GetStudentName(CStudent* pStudent)
{
return pStudent->GetName();
}

// 要导出到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),

// 全局函数(参数是对象指针)
def("GetStudentName", &GetStudentName),

// 导出全局函数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) // 大学生
// )

];

// 导出结构体SScore,虽然SScore是struct,仍要以类的方式进行导出,且需导出构造函数,谨记
module(L)
[
class_<SScore>("SScore") // 导出类名字"CStudent"
.def(constructor<>()) // 导出构造函数
.def_readwrite("name",&SScore::name) // 导出可读可写变量
.def_readwrite("score",&SScore::score) // 导出可读可写变量
];

// 导出类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) // 可读可写的属性
.def_readwrite("m_score", &CStudent::m_score) // 可读可写的属性(结构体类型)

// 导出类中的属性,另外一种办法
.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---------- C++开始访问lua中的函数,变量,table ------------\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,否则在导出类的属性时会被认为是函数。。。。。

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

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

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

lua测试代码如下:

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

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

-- 调用C++中的重载函数
print("\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("\ncall C++ enum")
-- 调用C++中的全局枚举
--print("enStudentType_Little = "..enStudentType_Little)

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

print("\nglobal function param is Class pointer")
local studentName = GetStudentName(student) -- 调用全局函数(函数参数是对象指针的)
print("GetStudentName = "..studentName)

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_score(struct) readwrite property")
print(student.m_score.name) -- 访问类的可读可写属性
print(student.m_score.score) -- 访问类的可读可写属性

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

测试结果如下:

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

 

 

标签:0.9,string,lua,windows,示例,导出,int,print,CStudent
From: https://blog.51cto.com/u_15912066/5936253

相关文章

  • linux centos 编译luabind-0.9.1 动态库 静态库
    编译步骤一.需先编译好lua,编译好静态库即可,编译lua的具体步骤如下:  1.lua5.1.5下载地址注意:貌似使用lua5.2版本来编译luabind会出现各种奇怪的报错,所以拿lua5.1做测......
  • centos7 redis5.0以后版本 集群部署示例
    简言1.redis5.0版本以前的集群部署是使用ruby脚本完成的,略为复杂2.本篇博客讲解redis5.0版本以后的集群部署,由于集成到了create_cluster中(位置:redis根目录/utils/create-c......
  • ubuntu16 redis5.0以后版本集群部署示例
    简言1.redis5.0版本以前的集群部署是使用ruby脚本完成的,略为复杂,具体示例见笔者的这篇博客,​​ubuntu16redis5.0以前版本集群部署示例_YZF_Kevin的博客2.本篇博客讲解red......
  • centos7 redis5.0以前版本 集群部署示例 - 第一篇
    简言1.redis5.0版本以前的集群部署是使用ruby脚本完成的,ruby脚本的安装少略麻烦(主要原因是系统自动安装的版本太低,无法部署集群,必须手动安装)2.redis5.0版本以后的集群部署......
  • ubuntu16 redis5.0以前版本集群部署示例
    简言1.redis5.0版本以前集群的部署是使用ruby脚本完成的,ruby脚本的安装少略麻烦(主要原因是系统自动安装的版本太低,无法部署集群,必须手动安装)2.redis5.0版本以后把集群的部......
  • jsoncpp在linux和windows下的编译及使用详解
    一:摘要1.JSON是一种轻量级的数据传输格式,全称为:JavaScriptObjectNotation,官方网址:​​​http://www.json.org/json-zh.html​​​3.JSONCPP是......
  • go windows开发环境安装
    安装golang下载下载地址:https://golang.org/dl/安装默认安装路径:C:\ProgramFiles\Go一路点击下一步PS:升级go版本可以直接卸载旧版本,然后安装新版本,环境变量与已经......
  • Python爬虫采集搞笑段子示例
    对于爬虫的用处不同的人有不同的看法,对于我而言,他是一门技能也是一门艺术,只有掌握其中的原理,才能让你体会到真正的快乐。下文就是我用python爬虫爬取搞笑段子的实例可以一起......
  • C#客户端实现域环境内Windows认证免密码自动身份认证登录
    C#客户端实现域环境内Windows认证免密码自动身份认证登录 客户端代码:///<summary>///认证客户端///</summary>publicclassAuthClient{......
  • 【读书笔记】Windows程序设计5
    Windows程序设计一、起步1.1.第一个Windows程序main.c#include<windows.h>intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,PSTRszCmdLine,in......