Lua和C++交互 学习记录之八:C++类注册为Lua模块
2016-09-22 17:20
676 查看
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍)
部分内容查阅自:《Lua 5.3 参考手册》中文版 译者 云风 制作 Kavcc
vs2013+lua-5.3.3
1.C++中学生Student类
①头文件Student.h
②实现文件student.cpp
2.C++中定义注册全局函数到Lua中
①头文件StudentRegFuncs.h
②实现文件StudentRegFuncs.cpp
③ C++和Lua之间的交互是通过lua_newuserdata创建出来的内存块进行交互的
这个函数分配一块指定大小的内存块, 把内存块地址作为一个完全用户数据压栈, 并返回这个地址。 宿主程序可以随意使用这块内存。
④注意传入参数的检查宏luaL_argcheck
如果cond条件不为true,则抛出一个错误报告调用的 C 函数的第 arg 个参数的问题。
⑤类型检查函数luaL_checktype
检查函数的第 arg 个参数的类型是否是 t。
3.将对应的全局函数注册到Lua中
①加入到注册模块列表中去
②注册到Lua中
4.在Lua中进行调用(Student为模块名)
可以看到,调用的方式需要使用模块名,并且第一个参数为创建的对象,和我们熟悉的面向对象的调用方式不一样。
Lua中面向对象的实现在下一节《Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类》。
Lua和C++交互系列:
《Lua和C++交互 学习记录之一:C++嵌入脚本》
《Lua和C++交互 学习记录之二:栈操作》
《Lua和C++交互 学习记录之三:全局值交互》
《Lua和C++交互 学习记录之四:全局table交互》
《Lua和C++交互 学习记录之五:全局数组交互》
《Lua和C++交互 学习记录之六:全局函数交互》
《Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块》
《Lua和C++交互 学习记录之八:C++类注册为Lua模块》
《Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类》
部分内容查阅自:《Lua 5.3 参考手册》中文版 译者 云风 制作 Kavcc
vs2013+lua-5.3.3
1.C++中学生Student类
①头文件Student.h
#pragma once #include <iostream> #include <string> class Student { public: //构造/析构函数 Student(); ~Student(); //get/set函数 std::string get_name(); void set_name(std::string name); unsigned get_age(); void set_age(unsigned age); //打印函数 void print(); private: std::string _name; unsigned _age; };
②实现文件student.cpp
#include "Student.h" Student::Student() :_name("Empty"), _age(0) { std::cout << "Student Constructor" << std::endl; } Student::~Student() { std::cout << "Student Destructor" << std::endl; } std::string Student::get_name() { return _name; } void Student::set_name(std::string name) { _name = name; } unsigned Student::get_age() { return _age; } void Student::set_age(unsigned age) { _age = age; } void Student::print() { std::cout << "name :" << _name << " age : " << _age << std::endl; }
2.C++中定义注册全局函数到Lua中
①头文件StudentRegFuncs.h
#pragma once #include "Student.h" #include "lua.hpp" //------定义相关的全局函数------ //创建对象 int lua_create_new_student(lua_State* L); //get/set函数 int lua_get_name(lua_State* L); int lua_set_name(lua_State* L); int lua_get_age(lua_State* L); int lua_set_age(lua_State* L); //打印函数 int lua_print(lua_State* L); //------注册全局函数供Lua使用------ static const luaL_Reg lua_reg_student_funcs[] = { { "create", lua_create_new_student }, { "get_name", lua_get_name }, { "set_name", lua_set_name }, { "get_age", lua_get_age }, { "set_age", lua_set_age }, { "print", lua_print }, { NULL, NULL }, }; int luaopen_student_libs(lua_State* L);
②实现文件StudentRegFuncs.cpp
#include "StudentRegFuncs.h" int lua_create_new_student(lua_State* L) { //创建一个对象指针放到stack里,返回给Lua中使用 Student** s = (Student**)lua_newuserdata(L, sizeof(Student*)); *s = new Student(); return 1; } int lua_get_name(lua_State* L) { //得到第一个传入的对象参数(在stack最底部) Student** s = (Student**)lua_touserdata(L, 1); luaL_argcheck(L, s != NULL, 1, "invalid user data"); //清空stack lua_settop(L, 0); //将数据放入stack中,供Lua使用 lua_pushstring(L, (*s)->get_name().c_str()); return 1; } int lua_set_name(lua_State* L) { //得到第一个传入的对象参数 Student** s = (Student**)lua_touserdata(L, 1); luaL_argcheck(L, s != NULL, 1, "invalid user data"); luaL_checktype(L, -1, LUA_TSTRING); std::string name = lua_tostring(L, -1); (*s)->set_name(name); return 0; } int lua_get_age(lua_State* L) { Student** s = (Student**)lua_touserdata(L, 1); luaL_argcheck(L, s != NULL, 1, "invalid user data"); lua_pushinteger(L, (*s)->get_age()); return 1; } int lua_set_age(lua_State* L) { Student** s = (Student**)lua_touserdata(L, 1); luaL_argcheck(L, s != NULL, 1, "invalid user data"); luaL_checktype(L, -1, LUA_TNUMBER); (*s)->set_age((unsigned)lua_tointeger(L, -1)); return 0; } int lua_print(lua_State* L) { Student** s = (Student**)lua_touserdata(L, 1); luaL_argcheck(L, s != NULL, 1, "invalid user data"); (*s)->print(); return 0; } int luaopen_student_libs(lua_State* L) { luaL_newlib(L, lua_reg_student_funcs); return 1; }
③ C++和Lua之间的交互是通过lua_newuserdata创建出来的内存块进行交互的
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
这个函数分配一块指定大小的内存块, 把内存块地址作为一个完全用户数据压栈, 并返回这个地址。 宿主程序可以随意使用这块内存。
④注意传入参数的检查宏luaL_argcheck
#define luaL_argcheck(L, cond,arg,extramsg) \ ((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
如果cond条件不为true,则抛出一个错误报告调用的 C 函数的第 arg 个参数的问题。
⑤类型检查函数luaL_checktype
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
检查函数的第 arg 个参数的类型是否是 t。
3.将对应的全局函数注册到Lua中
①加入到注册模块列表中去
static const luaL_Reg lua_reg_libs[] = { { "base", luaopen_base }, //系统模块 { "Student", luaopen_student_libs}, //模块名字Student,注册函数luaopen_student_libs { NULL, NULL } };
②注册到Lua中
//注册让lua使用的库 const luaL_Reg* lua_reg = lua_reg_libs; for (; lua_reg->func; ++lua_reg){ luaL_requiref(L, lua_reg->name, lua_reg->func, 1); lua_pop(L, 1); }
4.在Lua中进行调用(Student为模块名)
local student_obj = Student.create() Student.set_name(student_obj,"Jack") Student.print(student_obj)
可以看到,调用的方式需要使用模块名,并且第一个参数为创建的对象,和我们熟悉的面向对象的调用方式不一样。
Lua中面向对象的实现在下一节《Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类》。
Lua和C++交互系列:
《Lua和C++交互 学习记录之一:C++嵌入脚本》
《Lua和C++交互 学习记录之二:栈操作》
《Lua和C++交互 学习记录之三:全局值交互》
《Lua和C++交互 学习记录之四:全局table交互》
《Lua和C++交互 学习记录之五:全局数组交互》
《Lua和C++交互 学习记录之六:全局函数交互》
《Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块》
《Lua和C++交互 学习记录之八:C++类注册为Lua模块》
《Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类》
相关文章推荐
- Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
- Lua和C++交互 学习记录之四:全局table交互
- Lua和C++交互 学习记录之二:栈操作
- Lua和C++交互 学习记录之六:全局函数交互
- Lua和C++交互 学习记录之一:C++嵌入脚本
- Lua和C++交互 学习记录之五:全局数组交互
- Lua 与C/C++ 交互系列:利用模板技术在Lua Code中注册C++类
- Lua和C++交互 学习记录之三:全局值交互
- Lua 与C/C++ 交互系列:动态注册枚举enum到Lua Code中,在运行时在Lua Code中获取内省信息
- cocos2d-Lua与c++交互,lua如何绑定C++类。
- Lua和C++交互api学习
- C++ 和lua交互学习的三个例子
- Lua 与C/C++ 交互系列:注册枚举enum到Lua Code中
- Lua学习记录 — (8)模块与包
- Lua 与C/C++ 交互系列:注册枚举enum到Lua Code中
- LUA和C/C++交互-注册回调函数
- cocos2d-x学习笔记(十一)c++与lua交互回调函数的处理
- C/C++和Lua的交互
- 通过例子学习Lua(5) ---- Lua与C交互入门