Символ Idris FFI не найден

В последнее время я возился с Idris и решил попробовать поиграть с его Network.Socket библиотекой. Я запустил REPL, импортировал модуль и создал сокет с помощью команды socket. При попытке выполнить операцию IO я столкнулся со следующей ошибкой:

failed to construct ffun from (Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (2),Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (1),[])
Symbol "socket" not found
user error (Could not call foreign function "socket" with args [2,1,0])

Чтобы увидеть, была ли проблема связана с Network.Socket или просто с FFI в целом, я создал фиктивную функцию.

printf : String -> IO ()
printf = foreign FFI_C "printf" (String -> IO ())

Выполненный :x printf "Hello World" дает аналогичную ошибку:

Symbol "printf" not found
user error (Could not call foreign function "printf" with args ["hello world"])

Несмотря на все это, putStr работает нормально.

Я использую Idris 9.20, установленный через клику с -f FFI, установленным при компиляции. Я использую libffi версии 3.4, установленную через MacPorts.


person Kwarrtz    schedule 20.11.2015    source источник
comment
Я получаю ту же ошибку с idris 0.9.20.1, установленным через brew, однако установка printf в main и вызов :exec работает с предупреждением.   -  person Markus    schedule 29.11.2015


Ответы (1)


Я считаю, что это связано с тем, что Idris FFI работает по-разному в зависимости от того, компилируется или интерпретируется код. Когда код компилируется, FFI требует, чтобы на этапе генерации кода C именованная функция C находилась в области видимости, а при компоновке исполняемого файла C было связано правильное имя. Поскольку RTS Idris связывается с libc, это делает многие имена из libc работают без каких-либо дополнительных усилий (для некоторых имен может потребоваться %include, чтобы убедиться, что включен правильный заголовочный файл C, чтобы поместить их в область). Когда код интерпретируется, интерпретатор ищет вызовы FFI в списке библиотек, которые были загружены динамически, что требует другой директивы: %dynamic в файле или :dynamic в интерпретаторе. По умолчанию динамические библиотеки не загружаются, поэтому даже стандартные имена в libc не входят в область действия. Это можно исправить, включив %dynamic "libc" в файл или используя :dynamic "libc" в командной строке REPL для одного сеанса.

person Peter Amidon    schedule 24.08.2016