Common Lisp: значение 16777216 не соответствует ожидаемому типу (UNSIGNED-BYTE 24)

Я использую Clozure-CL на windows 7. Я написал простой класс «изображение» (ну, структуру) для теста.

(defmacro -> (struct slot) `(slot-value ,struct ,slot))

(defstruct 
  (image 
    (:constructor make-image (&key width height (bytes-per-pixel 4) 
        (pixels (make-array (* bytes-per-pixel (* width height))
                                :element-type '(unsigned-byte 8)))))
    (:print-function (lambda (img s k)
                       (declare (ignore k)) 
               (format s "image(~ax~a@~abpp)"
                               (-> img 'width) (-> img 'height)
                               (* 8 (-> img 'bytes-per-pixel))))))
  (width 0 :type '(unsigned-byte 32))
  (height 0 :type '(unsigned-byte 32))
  (bytes-per-pixel 4 :type '(unsigned-byte 32))
  (pixels nil))

К сожалению, когда я пытаюсь сделать это:

(make-image :width 2048 :height 2048)

Я получаю эту ошибку:

value 16777216 is not of the expected type (UNSIGNED-BYTE 24).
   [Condition of type TYPE-ERROR]

Вот трассировка стека (скопирована из slimv):

  0: (CCL::MAKE-UARRAY-1 207 16777216 NIL NIL NIL NIL NIL NIL NIL 16777216)
  1: (MAKE-IMAGE :WIDTH 2048 :HEIGHT 2048 :BYTES-PER-PIXEL 4 :PIXELS 16777216)
  2: (CCL::CALL-CHECK-REGS MAKE-IMAGE :WIDTH 2048 :HEIGHT 2048)
  3: (CCL::CHEAP-EVAL (MAKE-IMAGE :WIDTH 2048 :HEIGHT 2048))
  4: (SWANK::EVAL-REGION "(make-image :width 2048 :height 2048)\n")
  5: ((:INTERNAL SWANK::REPL-EVAL))
  6: (SWANK::TRACK-PACKAGE #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK::REPL-EVAL) #x19D56EAE>)
  7: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME REPL evaluation request." #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK::REPL-EVAL) #x19D56EFE>)
  8: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK::REPL-EVAL) #x19D56F26>)
  9: (SWANK::REPL-EVAL "(make-image :width 2048 :height 2048)\n")
 10: (CCL::CALL-CHECK-REGS SWANK:LISTENER-EVAL "(make-image :width 2048 :height 2048)\n")
 11: (CCL::CHEAP-EVAL (SWANK:LISTENER-EVAL "(make-image :width 2048 :height 2048)\n"))
 12: (SWANK:EVAL-FOR-EMACS (SWANK:LISTENER-EVAL "(make-image :width 2048 :height 2048)\n") "GAME" 135)
 13: (SWANK::PROCESS-REQUESTS NIL)
 14: ((:INTERNAL SWANK::HANDLE-REQUESTS))
 15: ((:INTERNAL SWANK::HANDLE-REQUESTS))
 16: (SWANK-BACKEND:CALL-WITH-DEBUGGER-HOOK #<Compiled-function SWANK:SWANK-DEBUGGER-HOOK #x186F1EF6> #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK::HANDLE-REQUESTS) #x1882D666>)
 17: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-OUTPUT* . #<SWANK-BACKEND::SLIME-OUTPUT-STREAM #x188247CE>) (*STANDARD-INPUT* . #<SWANK-BACKEND::SLIME-INPUT-STREAM #x188249DE>) ..))) #<CCL:COMPILED-LEXICAL-CLO..
 18: (SWANK::HANDLE-REQUESTS #<MULTITHREADED-CONNECTION  #x1880CB0E> NIL)
 19: (CCL::RUN-PROCESS-INITIAL-FORM #<PROCESS repl-thread(12) [Active] #x18824C8E> (#<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL CCL::%PROCESS-RUN-FUNCTION) #x18824B46>))

Насколько я понимаю, Clozure-CL использует некоторую внутреннюю функцию для создания байтовых массивов, и эта функция по какой-то причине ожидает 24-битные целочисленные аргументы для размера массива, а поскольку 16777216 равно 224, она не будет укладывается в 24-битное целое. Я хотел бы снять это ограничение. Как я могу решить эту проблему?

Редактировать

Я проверил документацию и обнаружил, что в 32-битной версии Clozure-CL максимальный размер массива (array-total-size-limit) равен (expt 2 24). У 64-битной версии ограничение гораздо больше, но все же можно ли что-то с этим сделать?


person SigTerm    schedule 21.08.2013    source источник


Ответы (1)


Как вы уже поняли, это ограничение 32-битной версии Clozure CL. 64-битная версия Clozure CL имеет большее ограничение.

На моем Mac:

? array-total-size-limit
72057594037927936

Что ты можешь сделать:

  • используйте несколько меньших массивов и спрячьте их за каким-нибудь интерфейсом. Болезненный.
  • используйте FFI для выделения массивов на стороне C. Немного болезненно. Убедитесь, что у вас есть проверка типа/границы и правильное управление памятью.
  • используйте 64-битную версию. Может это ваш вариант?

Ограничения реализации 32-битной версии изменить непросто, если вообще изменить.

person Rainer Joswig    schedule 21.08.2013
comment
Хорошо спасибо. На данный момент я, вероятно, откажусь от больших массивов (хотел выполнить некоторые незначительные манипуляции с изображениями / блицирование) и перенесу функции, которые могут потребовать их, в dll C++. Что касается 64-битной, это заманчиво, но я бы предпочел пока оставить приложение 32-битным... (так что мне не придется постоянно поддерживать две версии dll, которые будет использовать проект (. - person SigTerm; 21.08.2013
comment
@SigTerm: это разумно. Некоторые инструменты обработки изображений для Lisp используют библиотеки C. См., например: kogs-www.informatik. uni-hamburg.de/publikationen/pub-seppke/ и lisp-book.org /contents/chimg.pdf - person Rainer Joswig; 21.08.2013