Problem in luabind with default_converter and tables
===Edit===
The problem is actually much simpler than this, any wrapped function that takes a table is causing the problem. If I wrap a function that takes luabind::object, and call that function with a table argument, then the gc causes an invalid free(). I'm starting to think that this may be some kind of crazy compilation/linking problem, as my compiled luabind dylib has lua symbols in it (resulting in two copies of those symbols, one in that library and one in my binary). Maybe I have duplicates of some lua static variables or something? I might just be grasping at straws here.
===Edit===
Using luabind 0.9 and gcc 4.2.1 on mac os x 10.6
I'm seeing what could (maybe?) be a problem with using a default_converter from lua tables.
I'm trying to define converters for various list-like types in my code, specifically std::vector. When I pass a table to a c++ method with such a default_converter, lua crashes with free() on an invalid pointer as soon as the garbage collector is called.
I'm probably missing something simple here, but I can't figure it out.
Thanks!
* Lua Code *
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++ Code *
#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;
}
Yeah, I figured it out. Turns out that luabind didn't have any problems at all, except for the way it was built. The jam build system, on mac os x, causes the static lua library to be linked in with the luabind shared library, causing duplicate symbols (and duplicate static variables) when I link my final binary. It didn't have the entire lua library linked in though, so you still have to link liblua.a in again.
Take this explanation with a grain of salt, but it's my best guess; I'm not an expert at how the Mac OS X linker works. I do know that when I built luabind statically, everything works fine.
So, for anyone building lubabind in mac, build statically. There are also other problems with the jam built shared lib that you'd have to fix, like the fact that @executable_path is wrong. Static build was dead simple.
精彩评论