- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我一直在使用 LuaPlus 来使用脚本语言公开模块的功能。为此,LuaPlus 真的很棒,但我坚持清理我的暴露对象,因为我不知道如何处理删除代表我的 c++ 对象的 lua 对象,所以我可以正确释放 c++ 资源。
我使用 lua 表和元表来表示 cpp 对象,将指向 cpp 对象的指针作为表的 lightuserdata 参数“__object”传递,所以我可以做类似的事情
function foo()
local p = MyCppObject:new() //Create a cpp object and bind it to a table+metatable
p:do_something() //Correctly calls the cpp member function do_something
....
(exits scope) //No more references to p, so p is deleted.
end
函数退出后(或一段时间后),我希望得到对 metatable method "__gc" 的调用,我在其中调用内部 cpp 对象的删除,但我根本没有看到我的 cpp 回调被调用。我尝试使用 lua 的函数 collectgarbage 强制垃圾收集,多次调用我的函数以强制 lua 收集我的对象,但我看不到我的回调正在执行。最重要的是,我看到调用 collectgarbage("count") 的结果有时会减少,所以某些地方会被删除,但我不知道是什么。我检查了 lua 文档,但看不出我做错了什么:(
感谢任何评论!谢谢!
更新:添加了 c++ 代码端 + 添加了 Mud 指出的本地 + 我的测试示例
我创建了我的程序的这个小样本。 LuaShell 对象只是状态的包装器 + 读取命令行并执行从 std::cin 读取的字符串的循环
#include <iostream>
#include "LuaPlus.h"
class Point
{
private:
int x_,y_;
public:
Point(): x_(0), y_(0){}
Point(int a, int b): x_(a), y_(b){}
~Point() {std::cout << "Point "<< x_ << ","
<< y_ << "being deleted" << std::endl;}
int x() const { return x_;}
int y() const { return y_;}
};
LuaPlus::LuaObject metatable;
int new_point( LuaPlus::LuaState* state)
{
LuaPlus::LuaStack args(state);
//std::cout << "Creating point!!" << std::endl;
float x = 0, y = 0;
if ( args.Count() == 3)
{
if (args[2].IsNumber() && args[3].IsNumber())
{
x = args[2].GetFloat();
y = args[3].GetFloat();
}
}
Point* p = new Point(x,y);
LuaPlus::LuaObject lua_obj = state->CreateTable();
lua_obj.SetLightUserData("__object", p);
lua_obj.SetMetaTable( metatable );
return 1;
}
int my_gc_event( LuaPlus::LuaState* state)
{
std::cout << "Calling gc_event from lua" << std::endl;
return 0;
}
int main()
{
/* Creating the object that holds the Lua interpreter as well as
* the command line
*/
LuaShell::Shell shell(true);
LuaPlus::LuaObject globals = shell.get_state()->GetGlobals();
metatable = globals.CreateTable("PointMetaTable");
metatable.SetObject("__index", metatable);
metatable.Register("new", new_point);
metatable.Register("__gc",my_gc_event);
metatable.RegisterObjectDirect("x", (Point*)0 ,&Point::x);
metatable.RegisterObjectDirect("y", (Point*)0 ,&Point::y);
globals.SetObject("Point", metatable);
//Get into the read-command-line-until-quit loop.
shell.run();
return 0;
}
在 lua 端,我运行这个来测试。
? k,b = collectgarbage("count") print (k*1024)
> 33761
? for it=1,1000000 do foo() end
? k,b = collectgarbage("count") print (k*1024)
> 75315
? collectgarbage()
? k,b = collectgarbage("count") print (k*1024)
> 32363
如您所见,根据 lua 运行时有“一些”垃圾收集,但是当我看到我的进程的顶级报告时,内存只会上升,而不会下降。此外,我从来没有看到来自点析构函数的消息(预计因为我并没有真正调用它)或来自“my_gc_event”内部的消息(意外,因为我认为它在收集垃圾工作期间的某个时候被调用)。
再次感谢!
最佳答案
考虑到正确的答案(Mud 的 Prop )被埋在评论中,我认为最好在此处添加最终代码和答案。
正如 Mud 所说,我的问题是尝试使用表格来公开对象。虽然这样可行,但 lua 5.1 运行时(由 luaplus 使用)不会为表调用垃圾收集器事件 (__gc),因此我不得不使用 luaplus 中的 BoxPointer 辅助函数。还添加了一个映射来跟踪暴露对象的类型,因为它们作为 void* 传递,稍后您需要正确转换它们以进行适当的清理。使用一些模板技巧,我最终得到了一个非常简单的清理系统。代码如下(main函数不变,Point类定义不变)。
#include <iostream>
#include <map>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "LuaPlus.h"
#include "Shell.h"
//Function used to delete an object created and exposes to lua
template<typename type_to_delete>
void delete_wrapper(void* ptr)
{
type_to_delete* typed_ptr = static_cast<type_to_delete*>(ptr);
delete typed_ptr;
}
//My object metatable
LuaPlus::LuaObject metatable;
//Table to save function pointers for the correct deletion of exposed objects
std::map<void*,boost::function<void(void*)> > g_object_type_deleter;
int new_point( LuaPlus::LuaState* state)
{
LuaPlus::LuaStack args(state);
float x = 0, y = 0;
if ( args.Count() == 3)
{
if (args[2].IsNumber() && args[3].IsNumber())
{
x = args[2].GetFloat();
y = args[3].GetFloat();
}
}
Point* p = new Point(x,y);
//This used to be a table, but given the shortcoming with the gc, now using this version
LuaPlus::LuaObject lua_obj = state->BoxPointer(p);
lua_obj.SetMetaTable( metatable );
//Save the callback to delete the object we just created.
g_object_type_deleter[static_cast<void*> (p)] = boost::bind( delete_wrapper<Point> , _1);
return 1;
}
int my_gc_event( LuaPlus::LuaState* state)
{
//get the pointer lua is trying to delete.
void *p = state->UnBoxPointer(1);
//look for the delete callback with the type information
std::map<void*,boost::function<void(void*)> >::iterator it = g_object_type_deleter.find(p);
if (it == g_object_type_deleter.end() )
{
std::cout << "receiving callback to destroy object that was not indexed !" << std::endl;
return 0;
}
//Actually call the delete function passing the pointer as parameter
it->second(it->first);
return 0;
}
谢谢大家!
关于c++ - 垃圾收集事件的 LuaPlus 和 c++ 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11905357/
我想要一个函数在被 Lua 脚本调用时返回一个(键-值-)表。因此,我必须将表插入堆栈。 我知道如何将整数压入堆栈:state->PushInteger(10) 我也知道它如何处理字符串和其他数字,但
我想知道如何从 C++ 端创建和注册一个函数,该函数在从 Lua 端调用时返回一个表。 我尝试了很多东西,但没有任何效果。 :/ (抱歉代码太长)这例如是行不通的,因为 Register() 需要一个
我有一个关于使用 LuaPlus 的初学者问题。 我正在查看对象构造函数中的一些代码: m_MetaTable = g_pApp->m_pLuaStateManager->GetGlobalState
我找到了一个很好的教程,介绍如何使用 Visual Studio 2010 将 LuaPlus 实现到 C++ 项目中。 http://www.zynox.net/luaplus-1-compilin
我是 Lua/LuaPlus 的新手,正在尝试了解元表的工作原理。 在摘自手册的这段代码中: LuaObject metaTableObj = state->GetGlobals().CreateTa
我从这里(http://luaplus.org/projects/luaplus/files) 下载了visual2008 文件,但我不知道如何将它添加到我的项目中。它不像其他库,我只需将 inclu
In this guide创建函数以将怪物添加到表中并减少表中怪物的生命值。 您可以从 lua 脚本中像这样轻松地使用这两个函数: monster = objectMgr:CreateObject("
我下载了 JamPlus(在花了相当长的时间后发现这是所需的特定 Jam 衍生物,但没有随下载一起提供),并按照指示设置我的 PATH 变量,但它不起作用。 具体来说,Jam 列出了一系列错误,例如无
如何创建这样的 Lua 对象: players = { { pos = {x=12.43,y=6.91}, backpack = {22,54},
我一直在使用 LuaPlus 来使用脚本语言公开模块的功能。为此,LuaPlus 真的很棒,但我坚持清理我的暴露对象,因为我不知道如何处理删除代表我的 c++ 对象的 lua 对象,所以我可以正确释放
我的 Lua 脚本中有一种回调函数,我想从 C++ 端的不同线程调用它(每秒 0-100 次)。到目前为止,它基本上可以工作,但是一旦我在很短的时间内多次调用它,它就会使程序崩溃,从而导致错误,例如:
我目前正在使用 LuaPlus 开发一个项目,我需要能够使用 GUID,但似乎无法在 lua 中找到它们。当我为 lua 构建数据时,没有 setGUID,有设置数字、设置字符串等。还有一个 Set(
我想使用 LUAPlus 将 Lua 表函数链接到 C++ 变量。到目前为止,使用我可以在网上找到的信息,我已经设法使用 DoString("tableName:functionName") 调用了一
我是一名优秀的程序员,十分优秀!