我正在用SWIG包装的Lua中使用C ++类。
由于我使用的是单个Lua_State
,所以我希望能够在Lua脚本的特定块中释放变量而无需调用lua_close(L)
。
我决定使用package.preload['name']
,以便在需要时可以使用require 'name'
从其他块中访问一个块。
在执行以下操作后,我被告知package.preload
函数中的变量被释放:
package.preload['name'] = nil
package.loaded['name'] = nil
但是,即使在此之后,似乎我的自定义C ++类也没有被破坏。
这是我的完整示例代码:
在Main.cpp
#include "Main.h"
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaopen_my(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['test'] = function ()\n"
"local test = {}\n"
"local class = my.Class()\n"
"return test\n"
"end\n");
luaL_dostring(L, "require 'test'");
luaL_dostring(L, "package.preload['test'] = nil\n"
"package.loaded['test'] = nil\n");
}
在Main.h
#include "lua.hpp"
extern "C"
{
int luaopen_my(lua_State *L);
}
int main();
在MyBindings.h
#include "Main.h"
class Class
{
public:
Class()
{
std::cout << "Class Constructed" << std::endl;
};
~Class()
{
std::cout << "Class Destructed" << std::endl;
};
};
在MyBindings.i
中(用于生成MyBindings.cpp
的SWIG界面)
%module my
%{
#include "MyBindings.h"
%}
%include <stl.i>
%include <typemaps.i>
%include "MyBindings.h"
结果:
Class Constructed
为什么不调用类析构函数以及如何正确解构package.preload
函数中的类和变量?
答案 0 :(得分:2)
我无法重现您的问题,但是您的代码中还有其他缺陷,最明显的是缺少标题保护。 Main.h
文件不是必需的,而在MyBindings.h
文件中则不需要,因为它没有使用它。我不知道您使用的是哪个编译器,但是void main()
不是有效的C ++,该标准规定了int main()
。
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, "package.preload['test'] = function ()\n"
"local test = {}\n"
"local class = my.Class()\n"
"return test\n"
"end\n");
luaL_dostring(L, "require 'test'");
luaL_dostring(L, "package.preload['test'] = nil\n"
"package.loaded['test'] = nil\n");
lua_close(L);
}
MyBindings.h
#pragma once
#include <iostream>
class Class
{
public:
Class()
{
std::cout << "Class Constructed" << std::endl;
};
~Class()
{
std::cout << "Class Destructed" << std::endl;
};
};
MyBindings.i
%module my
%{
#include "MyBindings.h"
%}
%include "MyBindings.h"
示例调用:
$ swig -c++ -lua MyBindings.i
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 -fPIC -shared MyBindings_wrap.cxx -o my.so -llua5.2
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 -L . Main.cpp -l:my.so -llua5.2
$ LD_LIBRARY_PATH=. ./a.out
Class Constructed
Class Destructed
还应注意,Lua是一种垃圾收集语言,即,当垃圾收集器认为有必要时,析构函数将运行。您可以在C中使用lua_gc
或在Lua中使用collectgarbage
来手动运行垃圾收集器,但强烈建议您不要手动运行垃圾收集器,因为这通常会对性能产生负面影响(即使您手动运行它以提高性能)。只有在内存非常有限的环境中运行并且刚刚修剪了表之类的东西时,手动使用垃圾收集器才有意义。
无论如何,我使用上面编译的my.so
模块在Lua中为您准备了一个示例。
local my = require("my")
local x = my.Class()
print("Info: Deleting x")
x = nil
print("Info: Collecting garbage")
collectgarbage()
print("Info: Done :-)")
$ lua5.2 test.lua
Class Constructed
Info: Deleting x
Info: Collecting garbage
Class Destructed
Info: Done :-)
答案 1 :(得分:0)
您始终可以通过obj。〜class()显式调用d'tor。 如果您在Lua包装器中使用外部类,那么我不希望它们可以遵循C ++中存在的正确嵌套d'tor范式。