C++对象绑定到lua

lua.hpp

// lua.hpp  
// Lua header files for C++  
// <<extern "C">> not supplied automatically because Lua also compiles as C++  
  
#ifdef __cplusplus    
extern "C" {  
#endif  
    #include "lua.h"  
    #include "lualib.h"  
    #include "lauxlib.h"  
#ifdef __cplusplus  
}  
#endif  

Student.h

#ifndef __STUDENT_H_  
#define __STUDENT_H_  
  
  
#include "lua.hpp"  
  
class Student  
{  
	public:  
	    Student();  
	    void SetAge(int nAge);  
	    int GetAge();  
	  
	    int m_nAge;  
};  
  
  
#ifdef __cplusplus  
extern "C" {  
#endif  
    int luaopen_student(lua_State *L);  
#ifdef __cplusplus  
}  
#endif  
  
#endif 

Student.cpp

#include "Student.h"  
  
Student::Student()  
{  
    m_nAge = 0;  
}  
  
void Student::SetAge(int nAge)  
{  
    this->m_nAge = nAge;  
}  
  
  
int Student::GetAge()  
{  
    return this->m_nAge;  
}  
  
static int Create(lua_State *L) {  
    Student **s =  (Student**)lua_newuserdata(L, sizeof(Student*));  
    *s = new Student;  
  
    // 将userdata自定义数据与元表Meta_Student相关联  
    luaL_getmetatable(L, "Meta_Student");  
    lua_setmetatable(L, -2);  
  
    return 1;  
}  
  
  
static int SetAge(lua_State *L) {  
    Student **s = (Student**)luaL_checkudata(L, 1, "Meta_Student");  
    luaL_argcheck(L, s != NULL, 1, "invalid user data");  
  
    int nAge = (int)lua_tonumber(L, -1);  
    (*s)->SetAge(nAge);  
  
    return 0;  
}  
  
static int GetAge(lua_State *L) {  
    Student **s = (Student**)luaL_checkudata(L, 1, "Meta_Student");  
    luaL_argcheck(L, s != NULL, 1, "invalid user data");  
  
    lua_pushnumber( L, (lua_Number)((*s)->GetAge()) );  
  
    return 1;  
}  
  
static int AutoDel(lua_State *L) {  
    Student **s = (Student**)luaL_checkudata(L, 1, "Meta_Student");  
    luaL_argcheck(L, s != NULL, 1, "invalid user data");  
  
    delete (*s);  
  
    return 0;  
}  
  
  
int luaopen_student(lua_State *L)   
{  
    luaL_Reg reg[] =   
    {  
        {"Create", Create },  
        {NULL,NULL},  
    };  
  
    // 创建名字为“Meta_Student”元表  
    luaL_newmetatable(L, "Meta_Student");  
  
    //修改元表“Meta_Student”查找索引,把它指向“Meta_Student”自身  
    lua_pushvalue(L, -1);  
    lua_setfield(L, -2, "__index");  
  
    // GetAge方法  
    lua_pushcfunction(L, GetAge);  
    lua_setfield(L, -2, "GetAge");  
  
    // SetAge方法  
    lua_pushcfunction(L, SetAge);  
    lua_setfield(L, -2, "SetAge");  
  
    // 自动删除,如果表里有__gc,Lua的垃圾回收机制会调用它。  
    lua_pushcfunction(L, AutoDel);  
    lua_setfield(L,-2,"__gc");  
  
    // 注册reg中的方法到Lua中(“Student”相当于类名),reg中的方法相当于Student成员函数  
    luaL_register(L, "Student", reg);  
  
    return 1;  
}

main.lua

print(Student)    
--[[   
    1.打印Student地址  
    2.打印nil --> luaL_register(L, "Student", reg); 这段代码没有执行成功  
]]  
  
local p = Student.Create()  
--[[  
调用C++代码:  
static int Create(lua_State *L) {  
    Student **s =  (Student**)lua_newuserdata(L, sizeof(Student*));  
    *s = new Student;  
  
    // 将userdata自定义数据与元表Meta_Student相关联  
    luaL_getmetatable(L, "Meta_Student");  
    lua_setmetatable(L, -2);  
  
    return 1;  
}  
  
@retrun p-> Student*  
]]  
  
p:SetAge(1200)     -- 调用方法1  
p.SetAge(p, 1000)   -- 调用方法2  
--[[  
p:SetAge() p(userdata)没有注册SetAge方法, 就会寻找与p(userdata)相关联的元表Meta_Student有SetAge方法!并调用!  
  
调用C++代码:  
static int SetAge(lua_State *L) {  
    Student **s = (Student**)luaL_checkudata(L, 1, "Meta_Student");  
    luaL_argcheck(L, s != NULL, 1, "invalid user data");  
  
    int nAge = (int)lua_tonumber(L, -1);  
    (*s)->SetAge(nAge);  
  
    return 0;  
}  
  
]]  
  
  
print(p:GetAge())  
--[[  
调用C++代码:  
static int GetAge(lua_State *L) {  
    Student **s = (Student**)luaL_checkudata(L, 1, "Meta_Student");  
    luaL_argcheck(L, s != NULL, 1, "invalid user data");  
  
    lua_pushnumber( L, (lua_Number)((*s)->GetAge()) );  
  
    return 1;  
}  
]]  

main.cpp

// MyCma.cpp : 定义控制台应用程序的入口点。  
//  
  
//#include <SDKDDKVer.h>  
#include <stdio.h>  
#include <tchar.h>  
#include <windows.h>  
#include <string>  
#include "lua.hpp"  
#include "Student.h"  
  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
  
    lua_State* L = luaL_newstate();  
    luaL_openlibs(L);  
    luaopen_student(L);  
    luaL_dofile(L, "main.lua");  
    lua_close(L);  
  
    system("pause");  
  
    return 0;  
}  
最近的文章

光线反射算法

光线反射是一个非常重要的概念,或者说常识,这里我们来聊一下真实世界。现实世界中,我们眼睛之所以看到各种各样的物体,其原因就是太阳发出的光线照射到地球上,然后经过反射后进入人的眼睛,人的眼睛接收到光子后在视网膜上成像,然后通过生物信号传递给大脑,所以人就看到了这个世界。这里我们把太阳叫做“光源”,其实我们也有很多人造“光源”,比如电灯,激光等。比如在一间黑暗的屋子,我们打开屋里唯一一盏电灯,瞬间屋子就被照亮,我们的眼睛就能看到屋里的物体。ps:这里我们思考一个现象:我们正午站在一片操场上,四...…

阅读全文
更早的文章

lua

LUA和C/C++的沟通桥梁——栈Lua生来就是为了和C交互的,因此使用C扩展Lua或者将Lua嵌入到C当中都是非常流行的做法。要想理解C和Lua的交互方式,首先要回顾一下C语言是如何处理函数参数的。C函数和参数大家知道C语言是用汇编实现的,在汇编语言中可没有函数的概念,与函数对应的是叫做子过程的东西,子过程就是一段指令,一个子过程与它调用的子过程之间通过栈来进行参数的传递交互。在一个子过程在调用别的子过程之前,会按照约定的格式将要调用的子过程需要的参数入栈,在被调用的子过程中,可以按照约...…

阅读全文