【发布时间】:2012-05-06 04:40:31
【问题描述】:
我正在使用 Ryan Pavlik 的主发行版中的 luabind 0.9.1 和 Lua 5.1、Win XP SP3 上的 cygwin + 最新补丁 x86、boost 1.48、gcc 4.3.4。 Lua 和 boost 是 cygwin 预编译的版本。
我已经成功构建了静态和共享版本的 luabind。
两个版本都通过了所有测试,除了 test_object_identity.cpp 测试在两个版本中都失败了。
我已将问题追溯到以下问题: 如果表中的条目是为 NON 内置类创建的(即不是 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! (其实好像是nil)
但是,如果我使用 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 都会创建一个 NEW DISTINCT 对象(但如果您使用原始值或对象则不会)。
这里有一个小测试用例来证明这一点:
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,然后在通过 key 对象访问时被 7 覆盖。但是,当通过 tp 再次访问时,会创建一个新条目。这就是 gettable() 随后失败的原因。
谢谢, 大卫
【问题讨论】:
-
您解决过这个问题吗?当使用 int 值作为表的键时,我已经遇到了这个问题,例如local testTable = { [10]="green", [9]="orange", [8]="yellow" } - 如果我使用字符串而不是数字作为键 - 它工作正常 - 我将此表作为参数到一个 C++ 函数,我也得到了转换错误