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++注冊的類

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM