lua
2019-11-19 18:29:17

lua入门教程:C API 类方式注册

33 / 0 / 0 / 0

在c++中,允许我们创建类而lua并不是c++写出,我们如何把类注册到c++中去呢?需要一些通用的技巧,包括两个方面的东西,先把创建类的方法注册到全局函数中,在元表中注册各个成员函数。

创建一个CTest的类。

test.h

#ifndef __TEST_H__
#define __TEST_H__

class CTest
{
public:
    CTest();
    ~CTest();

    int getA();
    void setA(int a);

private:
    int m_a;
};

#endif

test.cpp

#include "test.h"

CTest::CTest()
{
    m_a = 0;
}

CTest::~CTest()
{
}

int CTest::getA()
{
    return m_a;
}

void CTest::setA(int a)
{
    m_a = a;
}

CTest中有两个方法,一个是getA,另外一个是setA

source.cpp

#include "test.h"

extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
};

static int CreateTest(lua_State* L)
{
    CTest** ppTest = (CTest**)lua_newuserdata(L, sizeof(CTest*));
    *ppTest = new CTest;
    luaL_getmetatable(L, "test");
    lua_setmetatable(L, -2);
    return 1;
}

static int TestGetA(lua_State* L)
{
    CTest** ppTest = (CTest**)luaL_checkudata(L, 1, "test");
    luaL_argcheck(L, ppTest != NULL, 1, "invalid user data");
    lua_pushnumber(L, (int)(*ppTest)->getA());
    return 1;
}

static int TestSetA(lua_State* L)
{
    CTest** ppTest = (CTest**)luaL_checkudata(L, 1, "test");
    luaL_argcheck(L, ppTest != NULL, 1, "invalid user data");
    int a = (int)lua_tointeger(L, 2);
    (*ppTest)->setA(a);
    return 0;
}

static int DeleteTest(lua_State* L)
{
    CTest** ppTest = (CTest**)luaL_checkudata(L, 1, "test");
    delete *ppTest;
    printf("test is deleted");
    return 0;
}

static const struct luaL_Reg test_reg_f[] =
{
    { "test", CreateTest },
    { NULL, NULL },
};

static const struct luaL_Reg test_reg_mf[] =
{
    { "TestGetA", TestGetA },
    { "TestSetA", TestSetA },
    { "__gc", DeleteTest },
    { NULL, NULL },
};

static int testModelOpen(lua_State* L)
{
    luaL_newlib(L, test_reg_f);
    return 1;
}

int main()
{
    int top = 0;
    lua_State* L = luaL_newstate();
    top = lua_gettop(L);
    luaopen_base(L);
    luaL_openlibs(L);
    top = lua_gettop(L);

    //加载模块
    luaL_requiref(L, "testModel", testModelOpen, 0);
    top = lua_gettop(L);

    //创建metatable
    luaL_newmetatable(L, "test");
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    luaL_setfuncs(L, test_reg_mf, 0);
    lua_pop(L, 1);
    top = lua_gettop(L);

    int ret = luaL_dofile(L, "test.lua");
    if (ret != 0)
    {
        printf("%s", lua_tostring(L, -1));
    }
    lua_close(L);

    getchar();
    return 1;
}

定义了 CreateTest ,主要是采用lua_newuserdata 把创建的CTest放在自定义的数据块中,并放在元表test下。

而对元表test进行相应的处理。

分别处理两个函数TestGetATestSetA,这两个函数分别处理的是成员函数,一个是getA,另外一个是setA

这里用到了元表中的几个元素,其中

{ "__gc", DeleteTest },

指的是垃圾回收,也就是调用完以后最后会调用__gc

lua_setfield(L, -2, "__index");

__index 指的是在查找某一个元素无法找到时,该用哪个进行替换。

PS: 如本文对您有疑惑,可加QQ:1752338621 进行讨论。

0 条评论

0
0
官方
微信
官方微信
Q Q
咨询
意见
反馈
返回
顶部