• Lua和C++交互 学习记录之八:C++类注册为Lua模块


    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍)

    部分内容查阅自:《Lua 5.3  参考手册》中文版 译者 云风 制作 Kavcc

     

    vs2013+lua-5.3.3

     

    1.C++中学生Student类

    ①头文件Student.h

     1 #pragma once
     2 
     3 #include <iostream>
     4 #include <string>
     5 
     6 class Student
     7 {
     8 public:
     9     //构造/析构函数
    10     Student();
    11     ~Student();
    12 
    13     //get/set函数
    14     std::string get_name();
    15     void set_name(std::string name);
    16     unsigned get_age();
    17     void set_age(unsigned age);
    18 
    19     //打印函数
    20     void print();
    21 
    22 private:
    23     std::string _name;
    24     unsigned _age;
    25 };

    ②实现文件student.cpp

     1 #include "Student.h"
     2 
     3 Student::Student()
     4     :_name("Empty"),
     5     _age(0)
     6 {
     7     std::cout << "Student Constructor" << std::endl;
     8 }
     9 
    10 Student::~Student()
    11 {
    12     std::cout << "Student Destructor" << std::endl;
    13 }
    14 
    15 std::string Student::get_name()
    16 {
    17     return _name;
    18 }
    19 
    20 void Student::set_name(std::string name)
    21 {
    22     _name = name;
    23 }
    24 
    25 unsigned Student::get_age()
    26 {
    27     return _age;
    28 }
    29 
    30 void Student::set_age(unsigned age)
    31 {
    32     _age = age;
    33 }
    34 
    35 void Student::print()
    36 {
    37     std::cout << "name :" << _name << " age : " << _age << std::endl;
    38 }

     

    2.C++中定义注册全局函数到Lua中

    ①头文件StudentRegFuncs.h

     1 #pragma once
     2 
     3 #include "Student.h"
     4 #include "lua.hpp"
     5 
     6 //------定义相关的全局函数------
     7 //创建对象
     8 int lua_create_new_student(lua_State* L);
     9 
    10 //get/set函数
    11 int lua_get_name(lua_State* L);
    12 int lua_set_name(lua_State* L);
    13 int lua_get_age(lua_State* L);
    14 int lua_set_age(lua_State* L);
    15 
    16 //打印函数
    17 int lua_print(lua_State* L);
    18 
    19 //------注册全局函数供Lua使用------
    20 static const luaL_Reg lua_reg_student_funcs[] = {
    21     { "create", lua_create_new_student },
    22     { "get_name", lua_get_name },
    23     { "set_name", lua_set_name },
    24     { "get_age", lua_get_age },
    25     { "set_age", lua_set_age },
    26     { "print", lua_print },
    27     { NULL, NULL },
    28 };
    29 
    30 int luaopen_student_libs(lua_State* L);

    ②实现文件StudentRegFuncs.cpp

     1 #include "StudentRegFuncs.h"
     2 
     3 int lua_create_new_student(lua_State* L)
     4 {
     5     //创建一个对象指针放到stack里,返回给Lua中使用
     6     Student** s = (Student**)lua_newuserdata(L, sizeof(Student*));
     7     *s = new Student();
     8     return 1;
     9 }
    10 
    11 int lua_get_name(lua_State* L)
    12 {
    13     //得到第一个传入的对象参数(在stack最底部)
    14     Student** s = (Student**)lua_touserdata(L, 1);
    15     luaL_argcheck(L, s != NULL, 1, "invalid user data");
    16 
    17     //清空stack
    18     lua_settop(L, 0);
    19 
    20     //将数据放入stack中,供Lua使用
    21     lua_pushstring(L, (*s)->get_name().c_str());
    22 
    23     return 1;
    24 }
    25 
    26 int lua_set_name(lua_State* L)
    27 {
    28     //得到第一个传入的对象参数
    29     Student** s = (Student**)lua_touserdata(L, 1);
    30     luaL_argcheck(L, s != NULL, 1, "invalid user data");
    31 
    32     luaL_checktype(L, -1, LUA_TSTRING);
    33 
    34     std::string name = lua_tostring(L, -1);
    35     (*s)->set_name(name);
    36 
    37     return 0;
    38 }
    39 
    40 int lua_get_age(lua_State* L)
    41 {
    42     Student** s = (Student**)lua_touserdata(L, 1);
    43     luaL_argcheck(L, s != NULL, 1, "invalid user data");
    44 
    45     lua_pushinteger(L, (*s)->get_age());
    46 
    47     return 1;
    48 }
    49 
    50 int lua_set_age(lua_State* L)
    51 {
    52     Student** s = (Student**)lua_touserdata(L, 1);
    53     luaL_argcheck(L, s != NULL, 1, "invalid user data");
    54 
    55     luaL_checktype(L, -1, LUA_TNUMBER);
    56 
    57     (*s)->set_age((unsigned)lua_tointeger(L, -1));
    58 
    59     return 0;
    60 }
    61 
    62 int lua_print(lua_State* L)
    63 {
    64     Student** s = (Student**)lua_touserdata(L, 1);
    65     luaL_argcheck(L, s != NULL, 1, "invalid user data");
    66 
    67     (*s)->print();
    68 
    69     return 0;
    70 }
    71 
    72 int luaopen_student_libs(lua_State* L)
    73 {
    74     luaL_newlib(L, lua_reg_student_funcs);
    75     return 1;
    76 }

     

    ③ C++和Lua之间的交互是通过lua_newuserdata创建出来的内存块进行交互的

    LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);

    这个函数分配一块指定大小的内存块, 把内存块地址作为一个完全用户数据压栈, 并返回这个地址。 宿主程序可以随意使用这块内存。

     

    ④注意传入参数的检查宏luaL_argcheck

    1 #define luaL_argcheck(L, cond,arg,extramsg)    
    2         ((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中

    ①加入到注册模块列表中去

    1 static const luaL_Reg lua_reg_libs[] = {
    2     { "base", luaopen_base }, //系统模块
    3     { "Student", luaopen_student_libs}, //模块名字Student,注册函数luaopen_student_libs
    4     { NULL, NULL }
    5 };

    ②注册到Lua中

    1 //注册让lua使用的库
    2 const luaL_Reg* lua_reg = lua_reg_libs;
    3 for (; lua_reg->func; ++lua_reg){
    4     luaL_requiref(L, lua_reg->name, lua_reg->func, 1);
    5     lua_pop(L, 1);
    6 }

     

    4.在Lua中进行调用(Student为模块名)

    1 local student_obj = Student.create()
    2 Student.set_name(student_obj,"Jack")
    3 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++注册的类

  • 相关阅读:
    python列表(包含列表方法)
    python数据类型和运算符
    python计算机初识
    python运行过程,变量,符号
    python·if语句
    python`while循环
    <select></select> php表单怎么传值
    thinkPhp3 空操作
    thinkphp3.1和3.2的<模板替换>的区别
    thinkphp3 空操作 如果为空会怎么样 empty name=""
  • 原文地址:https://www.cnblogs.com/chevin/p/5896858.html
Copyright © 2020-2023  润新知