我使用的是来自 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 测试在两个版本中都失败了。
我已将问题追踪到以下问题: 如果表中的条目是为非内置类(即非 int、字符串等)创建的,则无法检索该值。
下面是演示这一点的代码片段:
#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)
但是,如果我使用迭代遍历 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()。结果是一样的。我可以通过调试器看到调用了 key 的默认转换,所以我猜错误来自其中的某个地方,但我无法弄清楚问题到底是什么。
从下面这个简单的测试用例可以看出,Luabind 对复杂类型的转换肯定存在 bug:
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 都会创建一个新的 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,然后在通过键对象访问时被 7 覆盖。但是,当通过 tp 再次访问时,将创建一个新条目。这就是 gettable() 随后失败的原因。
谢谢, 大卫
最佳答案
免责声明:我不是 luabind 方面的专家。我完全有可能错过了一些关于 luabind 功能的信息。
首先,luabind在将test_param转换为Lua key时是做什么的?默认策略是复制。引用 luabind 文档:
This will make a copy of the parameter. This is the default behavior when passing parameters by-value. Note that this can only be used when passing from C++ to Lua. This policy requires that the parameter type has an accessible copy constructor.
在实践中,这意味着 luabind 将创建一个由 Lua 垃圾收集器拥有的新对象(称为“完整用户数据”)并将您的结构复制到其中。这是一件非常安全的事情,因为你对 c++ 对象做什么不再重要; Lua 对象会在没有任何开销的情况下保留下来。这是对按值排序的对象进行绑定(bind)的好方法。
为什么luabind每次传给Lua都会创建一个新对象?那么,它还能做什么呢?传递的对象的地址是否相同并不重要,因为原始的 c++ 对象在第一次传递给 Lua 后可能已经改变或被销毁。 (记住,它是按值复制到 Lua 的,而不是按引用复制的。)因此,只有 ==,luabind 必须维护一个列表,其中包含曾经传递给 Lua(可能是弱的)的该类型的每个对象,并比较你的反对每一个对象,看它是否匹配。 luabind 不会这样做(我认为也不应该这样做)。
现在,让我们看看 Lua 方面。即使 luabind 创建了两个不同的对象,它们仍然是相等的,对吧?那么,第一个问题是,除了某些内置类型之外,Lua 只能通过引用来保存对象。我之前提到的每个“完整用户数据”实际上都是一个指针。这意味着它们并不相同。
但是如果我们定义一个 __eq 元操作,它们是相等的。不幸的是,Lua 本身根本不支持这种情况。无论如何,用作表键的用户数据始终按身份进行比较。这实际上对用户数据来说并不是特别的;表格也是如此。 (请注意,为了正确支持这种情况,除了 __eq 之外,Lua 还需要覆盖对象上的哈希码操作。Lua 也不支持覆盖哈希码操作。)我不能代表 Lua 的作者为什么他们不这样做允许这样做(之前有人建议这样做),但它确实存在。
那么,有哪些选择呢?
When a pointer or reference to a registered class with a wrapper is passed to Lua, luabind will query for it's dynamic type. If the dynamic type inherits from wrap_base, object identity is preserved.
关于c++ - luabind:无法从非内置类索引的表中检索值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10316632/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'