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

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

2017-03-22 20:28 549 查看
人老了容易忘记以前做过事情,第一次写自己的博客!

本文使用的LUA5.1版本

lua.hpp

[cpp] view
plain copy

// 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

[cpp] view
plain copy

#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

[cpp] view
plain copy

#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

[plain] view
plain copy

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

[cpp] view
plain copy

// 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对象!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++对象 lua 绑定