6

这是我面临的一个问题:

我在 Wax 中创建了一个 NSDecimalNumber 行

    local x=NSDecimalNumber:initWithString("2.3") 

为此,我想使用以下行创建一个 NSDecimal

   local y=x:decimalValue() 

这会立即使程序崩溃。

要创建相同的体验,您需要创建一个基本的蜡项目,并将这两行作为函数 applicationDidFinishLaunching的纬线添加到 AppDelegate.lua 中。

问题:我怎样才能让它返回一个我可以传递的诚实的 NSDecimal?我实际上不需要自己查看或打印该号码。


附录

  1. 尽管互联网上普遍认为,NSDecimal 与 NSDecimalNumber 非常不同。第一个是 C 结构,第二个是 Obj-C 结构,我可以很好地使用它。
  2. 为了让 NSDecimalNumber 工作,我需要从wax-helpers.m 中注释掉第 222-224 行(NSNumber)和 241-246(NSValue)。
  3. NSDecimal 在 Foundation/NSNumber.h 中定义

运行时的输出:没有太多的堆栈跟踪,它只是默默地死去。在调试器(打开断点)中有以下(缩写)调用序列:

#0  0x027553f4 in objc_exception_throw
#1  0x0256e8d6 in __NSGetSizeAndAlignment
#2  0x0256ebd9 in __NSGetSizeAndAlignment
#3  0x025747b8 in __NSMS1
#4  0x02573f9c in +[NSMethodSignature signatureWithObjCTypes:]
#5  0x000342d0 in wax_selectorForInstance at wax_helpers.m:557
#6  0x00035bc2 in __index at wax_instance.m:303
#7  0x000181b9 in luaD_precall at ldo.c:319
#8  0x00018405 in luaD_call at ldo.c:376
#9  0x0002c488 in callTMres at lvm.c:88
#10 0x0002c74a in luaV_gettable at lvm.c:125
#11 0x0002dd26 in luaV_execute at lvm.c:467
#12 0x0001841c in luaD_call at ldo.c:377
#13 0x0000ddc8 in f_call at lapi.c:800
#14 0x0001758a in luaD_rawrunprotected at ldo.c:116
#15 0x0001879a in luaD_pcall at ldo.c:463
#16 0x0000de65 in lua_pcall at lapi.c:821
#17 0x00034e60 in wax_pcall at wax_helpers.m:826  
#18 0x00036be4 in pcallUserdata at wax_instance.m:580
#19 0x00036edc in wax_id_call at wax_instance.m:627

有时会有以下微小的堆栈跟踪:

wTest[36403:207] PANIC: 

Error
-----
Error calling 'applicationDidFinishLaunching:' on lua object '<AppDelegate: 0x6300e50>'
data/scripts/AppDelegate.lua:39: attempt to index local 'x' (a number value)
stack traceback:
    [C]: ?
data/scripts/AppDelegate.lua:39: in function <data/scripts/AppDelegate.lua:19>

这与调试器给出的匹配:Wax 正在尝试为数字值调用方法。

4

2 回答 2

2

重要编辑:好的,我很愚蠢(并且正在寻找简单问题的复杂答案)。快速阅读 Wax 博客,我发现https://github.com/probablycorey/wax/wiki/Overview提到了该toobjc功能。因此,它看起来像......

local x = (toobjc)(NDecimalNumber:initWithString("2.3"));

会做你想做的(即防止自动 Lua 类型转换)。我的语法可能略有错误,所以请尝试一下。我在下面留下了我的原始答案来说明另一个“解决方案”。


因此,查看 Wax(我不太熟悉),它在连接 Objective C 和 Lua 时执行的一项关键操作是将所有可以转换为合适的本地 Lua 类型的 Objective C 类型。这包括映射到 Lua 数字类型的NSNumber类型(例如)。NSDecimal

当然,您已经知道这一点,因此您将更改为wax-helpers.m. 唉,你所做的还不够——转换仍在发生,因此你NSDecimalNumber仍然成为一个数字。看起来,取决于它是否在你的 Lua 代码中使用,要么 Lua 崩溃(试图索引标量类型),要么 Objective C 桥崩溃。我不确定为什么有时您只会收到 Lua 跟踪错误(假设您的代码始终相同);它指出了一些关于内部 Wax 状态被违反的基本假设。

最好的解决方案是不涉及更换 Wax 的解决方案。目前,即使“修复”确实有效,您也完全禁用了类型之间的自动强制。我认为这会破坏很多 Wax 代码和习语。看看 Wax,它只会对它特别理解的某些 Foundation 类的子类执行自动转换;它不知道的任何对象类型仍然是对象。在这种情况下,我们陷入了NSValueandNSNumber转换,所以我的第一个建议是简单地包装NSDecimalNumber在 Wax 不理解的某个类中。就像是...

@interface MyDecimalWrapper : NSObject
{
  NSDecimalValue *myDecimal;
}

- (NSDecimalValue*)getDecimalValue;
- (NSDecimal*)getDecimal;

@end

@implementation MyDecimalWrapper

- (NSDecimalValue*)getDecimalValue { return [[myDecimal retain] autorelease] }
- (NSDecimal*)getDecimal { return [myDecimal decimalValue]; }

@end

可以在不显着更改代码的情况下将其添加到 Wax 中,并且使用它来携带 aNSDecimalValue过桥应该可以防止 Wax 的类型转换。当然,如果你getDecimalValue在 Lua 内部使用,结果会很快被包裹到一个 Luanumber中。如果您需要调用NSDecimalValueLua 底层的方法,只需从包装器上定义的等效方法代理它们。

如果这绝对不适合你,我可能会计算出 Wax 所需的更改。但是维护自己的端口,破坏大量现有的 Wax 代码和示例将是一个痛苦的世界。

NSDecimal切线:一旦你在 Lua 中有一个,我不确定你打算做什么。它是一个不透明的 C 结构,只能通过 Foundation 提供的 C 接口使用。

于 2011-06-24T19:54:38.900 回答
0

也许您应该尝试从字符串NSScanner创建。NSDecimal

于 2011-06-24T09:19:12.360 回答