1

===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;
}
4

1 に答える 1

2

ええ、私はそれを理解しました。ビルド方法を除いて、luabind にはまったく問題がなかったことがわかりました。mac os x 上の jam ビルド システムにより、静的 lua ライブラリが luabind 共有ライブラリにリンクされ、最終的なバイナリをリンクするときにシンボルが重複 (および静的変数が重複) します。ただし、lua ライブラリ全体がリンクされていないため、liblua.a を再度リンクする必要があります。

この説明は割り引いて考えてください。私は、Mac OS X リンカがどのように機能するかについての専門家ではありません。luabind を静的にビルドしたとき、すべてが正常に動作することはわかっています。

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.

于 2010-02-07T18:20:34.123 に答える