Попытка создать NSDecimal в iPhone-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, мне нужно закомментировать строки 222-224 (NSNumber) и 241-246 (NSValue) из wax-helpers.m.
  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 пытается вызвать метод для числового значения.

2 ответа

Важное редактирование: ОК, я тупой (и ищу сложные ответы на простые вопросы). Краткое чтение воскового блога, и я нахожу https://github.com/probablycorey/wax/wiki/Overview, в котором упоминается toobjc функция. Таким образом, это выглядит как...

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

будет делать то, что вы хотите (т.е. предотвратить автоматическое преобразование типов Lua). У меня может быть немного неправильный синтаксис, так что экспериментируйте. Я оставил свой оригинальный ответ ниже, чтобы проиллюстрировать другое "решение".


Итак, просматривая Wax (с которым я не очень хорошо знаком), одним из ключевых действий, которые он выполняет при соединении Objective C и Lua, является преобразование всех возможных типов Objective C в подходящие нативные типы Lua. Это включает NSNumber типы (такие как NSDecimal), которые сопоставлены с типами чисел Lua.

Конечно, вы уже знаете это, следовательно, ваши изменения в wax-helpers.m, Увы, то, что вы сделали, не совсем достаточно - конверсии все еще происходят, и, следовательно, ваши NSDecimalNumber все еще становится числом. Кажется, что в зависимости от того, используется ли это в вашем коде Lua, либо Lua взрывается (пытается индексировать скалярный тип), либо взрывается мост Objective C. Я не уверен, почему вы иногда получаете ошибку трассировки Lua (при условии, что ваш код всегда идентичен); это указывает на некоторые основные предположения о нарушении внутреннего состояния воска.

Лучшее решение будет такое, которое не требует замены воска. На данный момент, даже если "исправление" сработало, вы полностью отключили автоматическое приведение между типами. Это, я полагаю, сломает довольно много воскового кода и идиом. Что касается Wax, он будет выполнять только автоматические преобразования для типов, которые подклассируют определенные классы Foundation, которые он специально понимает; любой тип объекта, о котором он не знает, остается объектом. В этом случае мы попали в NSValue а также NSNumber преобразование, поэтому мое первое предложение - просто обернуть NSDecimalNumber в каком-то классе, который не понимает Воск. Что-то вроде...

@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 без значительного изменения его кода, и с помощью этого NSDecimalValue через мост должен предотвратить преобразование типа воска. Конечно, если вы используете getDecimalValue внутри Lua, результат будет быстро обернут в Lua number, Если вам нужно вызвать методы на основе NSDecimalValue в Lua просто прокси их из эквивалентных методов, определенных в оболочке.

Если это абсолютно не работает для вас, я, вероятно, могу отработать изменения, необходимые для воска. Но это будет непростой задачей - поддерживать свой собственный порт и ломать множество существующих Wax-кода и примеров.

Тангенциально: я не уверен, что вы собираетесь делать с NSDecimal как только у вас есть один в Lua. Это непрозрачная структура C, которую можно использовать только через интерфейс C, предоставляемый Foundation.

Может тебе стоит попробовать NSScanner создавать NSDecimal из строки

Другие вопросы по тегам