Ракетка FFI - пример использования массива C (_array)? - PullRequest
1 голос
/ 25 июня 2019

Я обертываю функцию C, которая принимает указатель в качестве аргумента и обрабатывает его либо как указатель типа int, либо указатель с плавающей точкой, либо как массив значений типа int или float, в зависимости от другого аргумента.Функция является частью рендерера в игре и вызывается много (60+) раз в секунду.

Итак, с учетом сказанного я знаю, что могу использовать _list для передачи аргумента типа массива, но

  • это фрагментирует кучу?Если я правильно понимаю, ракетка вызывает malloc перед каждым вызовом, а free сразу после

  • ей нужен определенный тип, поэтому мне нужно будет создать 2 функции (однудля _int, один для _float), который не был бы идеальным

Я наткнулся на https://docs.racket -lang.org / foreign / C_Array_Types.html , и это, кажется, именно то, что я хочу - и более эффективный («Массив не копируется; представление Racket поддерживается базовым представлением C»), а также подходит для нескольких типов («он может иметь другойтип элемента, если этот тип соответствует макету ожидаемого типа ").

Проблема в том, что я не могу найти способ, как построить его со стороны Ракетки?Все эти утверждения возвращают #f, и у меня нет идей

#lang racket

(require ffi/unsafe)

(displayln (array? (make-array-type _float 5)))
(displayln (array? (_array _float 5)))
(displayln (array? (malloc (_array _float 5))))
(displayln (array? (malloc (make-array-type _float 5))))

1 Ответ

2 голосов
/ 25 июня 2019

Функции make-array-type и _array создают типы C , которые являются простыми значениями времени выполнения Racket, которые описывают, как преобразовывать виды значений в и из представлений уровня C: например, _unt8 это тип C.Предикат array? распознает фактические значения, которые представлены типом C на основе _array, а не самим типом C.

Что касается построения значения массива, документы говорят:

Поскольку массив обрабатывается как структура, приведение типа указателя к типу массива не работает.Вместо этого используйте ptr-ref с указателем, тип массива, созданный с помощью _array, и индекс 0, чтобы преобразовать указатель в представление Racket, которое работает с array-ref и array-set!.

Воткак это работает на практике - в документации можно использовать пример:

#lang racket

(require ffi/unsafe
         rackunit)

(define 5floats (_array _float 5))

(check-true
 (array? (ptr-ref (malloc 5floats) 5floats)))

Для дальнейшего использования сообщество Racket гораздо активнее в списке рассылки пользователей ракеток и в Slack, чем в переполнении стека.

...