Проблема в luabind с default_converter и таблицы
Вопрос
=== РЕДАКТИРОВАТЬ ===
Проблема на самом деле намного проще, чем эта, любая обернутая функция, которая принимает таблицу, вызывает проблему. Если я оберную функцию, которая принимает объект Luabind :: и назову эту функцию с помощью аргумента таблицы, то GC вызывает недействительный свободный (). Я начинаю думать, что это может быть какая -то сумасшедшая компиляция/проблема связывания, поскольку в моем составленном Luabind Dylib есть символы 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 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;
}
Решение
Да, я понял это. Оказывается, у Луабинда вообще не было проблем, за исключением того, как он был построен. Система сборки JAM, на Mac OS X, вызывает связанную статическую библиотеку Lua с общей библиотекой Luabind, вызывая дублирующиеся символы (и дублирующие статические переменные), когда я связываю свой последний бинар. У него не было весь Библиотека Lua связана, так что вам все равно придется связать Liblua.a снова.
Возьмите это объяснение с целью соли, но это мое лучшее предположение; Я не эксперт в том, как работает линкер Mac OS X. Я знаю, что когда я построил Luabind по статически, все работает нормально.
Итак, для тех, кто строит Любабинд в Mac, постройте статически. Есть также и другие проблемы со встроенной общей LIB JAM, которые вам придется исправить, например, тот факт, что @Executable_Path неверен. Статическая сборка была мертвой простой.