您的位置:首页 > 编程语言 > Lua

使用LUA userdata手动绑定C++对象

2016-08-21 01:56 381 查看
人老了容易忘记以前做过事情,第一次写自己的博客! 

本文使用的LUA5.1版本

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;
}

特别注意: 使用lua userdata创建 C++  Student对象生命周期的问题!我使用lua gc删除C++  Student对象!

关于生命周期可以参考cocos2d-x自动释放池,也可以考虑一下云风大神博文!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lua userdata 绑定 C++