idris_newbuffer
- это функция C, используемая Data.Buffer
. От документов до поставщиков типа :
Если мы хотим вызывать наши сторонние функции из интерпретируемого кода (такого как REPL или поставщик типов), нам нужно динамически связать библиотеку, содержащую нужные нам символы.
Таким образом, каждая функция, использующая FFI, должна иметь связанную динамическую библиотеку. Это было бы Data.Buffer
и Data.ByteArray
. Давайте сосредоточимся на первом и посмотрим, какие проблемы возникают:
Так что Data.Buffer
требуется %dynamic "idris_buffer.so"
(и не только %include C "idris_buffer.h"
, который у него есть в настоящее время). Вы можете скопировать idris/rts/idris_buffer.(h|c)
и удалить функцию, которая требует другого rts-материала. Чтобы скомпилировать общую библиотеку, запустите:
cc -o idris_buffer.so -fPIC -shared idris_buffer.c
При использовании модифицированного Data.Buffer
вы все равно получите ошибку:
Could not use <<handle {handle: ram.mem}>> as FFI arg.
Вызов FFI: Data.Buffer.readBufferFromFile
. Аргумент File
вызывает проблемы. Это потому, что Идрис видит, что используется openFile
(еще одна функция C) и
преобразует его в вызов Haskell . С одной стороны, это хорошо, потому что во время компиляции мы интерпретируем код Idris, и это делает следующие функции вроде readLine
C / JS / Node /… agnostic. Но в этом случае, к сожалению, бэкэнд на Haskell не поддерживает дескриптор возвращаемого файла для вызовов FFI . Таким образом, мы можем написать еще одну fopen : String -> String -> IO Ptr
функцию, которая делает то же самое, но имеет другое имя, поэтому Ptr
останется Ptr
, как это можно использовать в вызовах FFI.
С этим сделано, есть еще одна ошибка благодаря встроенным модулям:
Could not use prim__registerPtr (<<ptr 0x00000000009e2bf0>>) (65546) as FFI arg.
Data.Buffer
использует ManagedPtr
в своем бэкэнде. И да, это также не поддерживается в вызовах FFI. Поэтому вам нужно изменить их на Ptr
. Думаю, оба этих могут поддерживаться в компиляторе.
Наконец все должно работать для действительного %provide (mem : Buffer)
. Но нет, потому что:
Can't convert pointers back to TT after execution.
Несмотря на то, что Idris теперь может читать файл во время компиляции, он не может сделать Buffer
или что-либо еще с Pnt
доступным для выполнения - и это вполне разумно. Наличие всего лишь указателя на то, когда программа была скомпилирована, является случайной вещью во время выполнения. Поэтому вам нужно либо преобразовать данные в результат в поставщике, либо использовать промежуточный формат, например Provider (List Bits8)
.
Я сделал короткий пример , чтобы List Bits8
был доступен в main
. Buffer
в основном Data.Buffer
с _openFile
и Pnt
вместо ManagedPtr
. Я надеюсь, что это поможет вам как-то, но, возможно, некоторые из людей, которые занимаются компиляцией, могут дать больше информации.