如何在 Lua 中手动销毁封装的 C++ 类

我想知道在 Lua 中是否可能手动销毁 C++ 类。

我尝试将 nil 分配给一个类,但似乎不起作用。

Main.cpp

#include "lua.hpp"

extern "C" int luaopen_my(lua_State *L);

int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaopen_my(L);
    lua_settop(L, 0);
    luaL_dostring(L, "local class = my.Class()\n"
                     "class = nil\n");
//    lua_close(L);
}

MyBindings.h

#pragma once
#include <iostream>

class Class
{
public:
    Class()
    {
        std::cout << "Class 构造" << std::endl;
    };
    ~Class()
    {
        std::cout << "Class 销毁" << std::endl;
    };
};

MyBindings.i

%module my
%{
#include "MyBindings.h"
%}

%include "MyBindings.h"

我得到的结果:

Class 构造

我期望的结果:

Class 构造
Class 销毁

如果我调用 lua_close(L); 或手动调用一个垃圾回收器 lua_gc(L, LUA_GCCOLLECT, 0); 就可以正常工作

但是我想学习是否有其他方法在 Lua 中手动销毁 C++ 类。

点赞
用户1944004
用户1944004

我猜 Class 是在你的程序中封装某种资源,你想要回收内存。为此,你可以模仿 std::fstream 的行为。你可以在任何时候调用 close() 方法来回收资源。如果你没有显式调用 close(),析构函数会为你调用它。然而,这意味着你需要在对象中编码有效状态。我使用一个布尔值来实现,需要在任何访问之前检查它。

我假设只是为了演示,你省略了 lua_close(L),但你永远不应该在关闭 Lua 状态之前退出程序。否则,可能不会调用最终器。例如,当突然退出而不调用 lua_close(L) 时,缓冲内容可能没有被写入文件。

MyBindings.i

%module my
%{
#include "MyBindings.h"
%}

%include "MyBindings.h"

MyBindings.h

#pragma once
#include <iostream>
#include <stdexcept>

class Class {
    bool m_valid{true};

public:
    Class() { std::cout << "Class Constructed" << std::endl; }

    void action() {
        if (!m_valid) {
            throw std::runtime_error("Use after free");
        }
        // do something
    }

    void close() {
        std::cout << "Class Destructed" << std::endl;
        m_valid = false;
    }

    ~Class() {
        if (m_valid) {
            close();
        }
    }
};

Main.cpp

#include <iostream>
#include "lua.hpp"

extern "C" int luaopen_my(lua_State *L);

int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaopen_my(L);
    lua_settop(L, 0);
    if (luaL_dostring(L, "local class = my.Class()\n"
                         "class:close()\n") != 0) {
        std::cerr << lua_tostring(L, -1) << '\n';
        lua_pop(L, 1);
    }
    std::cout << "Closing...\n";
    lua_close(L);
}

示例调用:

$ swig -c++ -lua MyBindings.i
$ clang++ -Wall -Wextra -Wpedantic -std=c++11 -I /usr/include/lua5.2/ Main.cpp MyBindings_wrap.cxx -llua5.2
$ ./a.out
Class Constructed
Class Destructed
Closing...
2018-08-03 22:34:29