Проблема в luabind с default_converter и таблицами - PullRequest
1 голос
/ 07 февраля 2010

=== Редактирование ===

Проблема на самом деле намного проще, чем любая другая функция, которая берет таблицу, вызывает проблему. Если я оберну функцию, которая принимает luabind :: object, и вызову эту функцию с аргументом таблицы, то gc вызовет недопустимый метод free (). Я начинаю думать, что это может быть какая-то сумасшедшая проблема компиляции / компоновки, поскольку в моем скомпилированном dulib luabind есть символы lua (в результате получается две копии этих символов, одна в этой библиотеке и одна в моем двоичном файле). Может быть, у меня есть дубликаты некоторых статических переменных lua или что-то? Я мог бы просто хвататься за соломинку здесь.

=== Редактирование ===

Использование luabind 0.9 и gcc 4.2.1 на Mac OS x 10.6

Я вижу, в чем может быть (может быть?) Проблема с использованием default_converter из таблиц lua.

Я пытаюсь определить конвертеры для различных спискообразных типов в моем коде, в частности, std :: vector. Когда я передаю таблицу методу c ++ с таким default_converter, lua аварийно завершает работу с free () на неверном указателе, как только вызывается сборщик мусора.

Я, вероятно, упускаю что-то простое здесь, но я не могу понять это.

Спасибо!

* Код 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;
}

1 Ответ

2 голосов
/ 07 февраля 2010

Да, я понял это. Оказывается, у luabind вообще не было никаких проблем, за исключением того, как он был построен. Система сборки jam в Mac OS X вызывает связывание статической библиотеки lua с разделяемой библиотекой luabind, вызывая дублирование символов (и дублирование статических переменных), когда я связываю свой последний двоичный файл. Тем не менее, в нее не была включена вся библиотека lua, поэтому вам все равно придется снова связать liblua.a.

Прими это объяснение с крошкой соли, но это мое лучшее предположение; Я не эксперт в том, как работает компоновщик Mac OS X. Я знаю, что когда я статически строил luabind, все работало нормально.

Итак, для любого, кто строит lubabind в mac, постройте статически. Есть также другие проблемы со встроенной общей библиотекой, которую вы должны исправить, например, тот факт, что @executable_path неверен. Статическая сборка была невероятно простой.

...