luabind的问题与default_converter和表格
题
===编辑===
问题实际上比这要简单得多,任何占用表的包装功能都会引起问题。如果我包装一个将Luabind ::对象的函数,并使用表参数调用该函数,则GC会导致无效的Free()。我开始认为这可能是某种疯狂的汇编/链接问题,因为我编译的Luabind Dylib包含LUA符号(导致了这些符号的两个副本,一个在该库中,一个在我的二进制中)。也许我有一些LUA静态变量的重复项?我可能只是在这里抓住稻草。
===编辑===
在Mac OS X 10.6上使用Luabind 0.9和GCC 4.2.1
我看到(也许?)使用LUA表中的Default_converter是一个问题。
我正在尝试为我的代码(特别是STD :: vector)中的各种列表式类型定义转换器。当我使用这样的default_converter将表格传递到C ++方法时,一旦调用了垃圾收集器,LUA就会在无效的指针上崩溃()。
我可能在这里错过了一些简单的东西,但我无法弄清楚。
谢谢!
* LUA代码 *
function first ()
-- Doesn't crash
-- t = TestClass(1, 3)
-- Crashes
t = TestClass({1, 2, 3})
print(t:get(0))
print(t:get(1))
print(t:get(2))
end
function second ()
print("About to call collectgarbage...")
collectgarbage()
print("Done calling collectgarbage!")
end
function test ()
first()
second()
end
* C ++代码 *
#include <iostream>
#include <lua.hpp>
#include <luabind/luabind.hpp>
#include <luabind/operator.hpp>
using namespace std;
using namespace luabind;
namespace luabind {
template<typename ListType>
struct default_converter<std::vector<ListType> > : native_converter_base<std::vector<ListType> > {
static int compute_score(lua_State* L, int index) {
return lua_type(L, index) == LUA_TTABLE ? 0 : -1;
}
std::vector<ListType> from(lua_State* L, int index) {
std::vector<ListType> list;
for (luabind::iterator i(luabind::object(luabind::from_stack(L, index))), end; i != end; ++i)
list.push_back(luabind::object_cast<ListType>(*i));
return list;
}
void to(lua_State* L, const std::vector<ListType>& l) {
luabind::object list = luabind::newtable(L);
for (size_t i = 0; i < l.size(); ++i)
list[i+1] = l[i];
list.push(L);
}
};
}
class TestClass {
public:
TestClass(std::vector<int> v) : m_vec(v) {}
TestClass(int b, int e) {
for (int i = b; i <= e; ++i)
m_vec.push_back(i);
}
int get(size_t i) const {
return m_vec[i];
}
private:
std::vector<int> m_vec;
};
int main(int argc, char** argv) {
if (argc != 2) {
cout << "usage: " << argv[0] << " <scriptname>" << endl;
return -1;
}
std::string scriptName = argv[1];
lua_State* L = (lua_State*) lua_open();
luaL_openlibs(L);
open(L);
module(L)
[
class_<TestClass>("TestClass")
.def(constructor<std::vector<int> >())
.def(constructor<int, int>())
.def("get", &TestClass::get)
];
if (luaL_loadfile(L, scriptName.c_str()) || lua_pcall(L, 0, 0, 0)) {
cout << "Script error: " << lua_tostring(L, -1) << endl;
return -1;
}
call_function<void>(globals(L)["test"]);
lua_close(L);
return 0;
}
解决方案
是的,我发现了。事实证明,除了建造方式外,Luabind根本没有任何问题。 Mac OS X上的JAM构建系统使静态LUA库与Luabind共享库链接在一起,当我链接我的最终二进制文件时,会导致重复的符号(和重复的静态变量)。它没有 全部的 lua库已链接,因此您仍然必须再次链接liblua.a。
用一粒盐进行这种解释,但这是我最好的猜测。我不是Mac OS X Linker工作方式的专家。我确实知道,当我静态地构建Luabind时,一切正常。
因此,对于在Mac中建造Lubabind的任何人,都可以静态地构建。您必须修复的JAM内置的共享LIB还有其他问题,例如@ExeCutable_path是错误的事实。静态构建很简单。