Я использую luabind 0.9.1 из основного дистрибутива Райана Павлика с Lua 5.1, cygwin на Win XP SP3 + последние патчи x86, boost 1.48, gcc 4.3.4. Lua и boost — это предварительно скомпилированные версии cygwin.
Я успешно создал luabind как в статической, так и в общей версии.
Обе версии проходят все тесты, ЗА ИСКЛЮЧЕНИЕМ теста test_object_identity.cpp, который не проходит в обеих версиях.
Я отследил проблему до следующей проблемы: если запись в таблице создана для НЕ встроенного класса (т. е. не int, string и т. д.), значение НЕ МОЖЕТ быть получено.
Вот кусок кода, демонстрирующий это:
#include "test.hpp"
#include <luabind/luabind.hpp>
#include <luabind/detail/debug.hpp>
using namespace luabind;
struct test_param
{
int obj;
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def_readwrite("obj", &test_param::obj)
];
test_param temp_object;
object tabc = newtable(L);
tabc[1] = 10;
tabc[temp_object] = 30;
TEST_CHECK( tabc[1] == 10 ); // passes
TEST_CHECK( tabc[temp_object] == 30 ); // FAILS!!!
}
tabc[1] действительно равен 10, а tabc[temp_object] НЕ равен 30! (на самом деле, кажется, ноль)
Однако, если я использую iterate для просмотра записей tabc, есть две записи с ПРАВИЛЬНЫМИ парами ключ/значение.
Любые идеи?
Кстати, перегружая оператор == следующим образом:
#include <luabind/operator.hpp>
struct test_param
{
int obj;
bool operator==(test_param const& rhs) const
{
return obj == rhs.obj;
}
};
и
module(L)
[
class_<test_param>("test_param")
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
Не меняет результат.
Я также пытался переключиться на settable() и gettable() с помощью оператора []. Результат тот же. Я вижу с помощью отладчика, что вызывается преобразование ключа по умолчанию, поэтому я предполагаю, что ошибка возникает где-то там, но я не могу понять, в чем именно проблема.
Как показывает следующий простой тестовый пример, в преобразовании Luabind для сложных типов определенно есть ошибка:
struct test_param : wrap_base
{
int obj;
bool operator==(test_param const& rhs) const
{ return obj == rhs.obj ; }
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def(constructor<>())
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
object tabc, zzk, zzv;
test_param tp, tp1;
tp.obj = 123456;
// create new table
tabc = newtable(L);
// set tabc[tp] = 5;
// o k v
settable( tabc, tp, 5);
// get access to entry through iterator() API
iterator zzi(tabc);
// get the key object
zzk = zzi.key();
// read back the value through gettable() API
// o k
zzv = gettable(tabc, zzk);
// check the entry has the same value
// irrespective of access method
TEST_CHECK ( *zzi == 5 &&
object_cast<int>(zzv) == 5 );
// convert key to its REAL type (test_param)
tp1 = object_cast<test_param>(zzk);
// check two keys are the same
TEST_CHECK( tp == tp1 );
// read the value back from table using REAL key type
zzv = gettable(tabc, tp1);
// check the value
TEST_CHECK( object_cast<int>(zzv) == 5 );
// the previous call FAILS with
// Terminated with exception: "unable to make cast"
// this is because gettable() doesn't return
// a TRUE value, but nil instead
}
Надеюсь, кто-то умнее меня сможет это понять, спасибо
Я обнаружил проблему в том факте, что Luabind создает НОВЫЙ ОТЛИЧНЫЙ объект КАЖДЫЙ раз, когда вы используете сложное значение в качестве ключа (но это НЕ происходит, если вы используете примитивное значение или объект).
Вот небольшой тестовый пример, демонстрирующий это:
struct test_param : wrap_base
{
int obj;
bool operator==(test_param const& rhs) const
{ return obj == rhs.obj ; }
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def(constructor<>())
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
object tabc, zzk, zzv;
test_param tp;
tp.obj = 123456;
tabc = newtable(L);
// o k v
settable( tabc, tp, 5);
iterator zzi(tabc), end;
std::cerr << "value = " << *zzi << "\n";
zzk = zzi.key();
// o k v
settable( tabc, tp, 6);
settable( tabc, zzk, 7);
for (zzi = iterator(tabc); zzi != end; ++zzi)
{
std::cerr << "value = " << *zzi << "\n";
}
}
Обратите внимание, что tabc[tp] сначала имеет значение 5, а затем заменяется на 7 при доступе через объект ключа. Однако при СНОВА доступе через tp создается новая запись. Вот почему gettable() впоследствии дает сбой.
Спасибо, Дэвид