• ffi народ, а расскажите как работает FFI там, где он работает. Вроде в Хаскеле говорят неплохая реализация есть.
    Интересно: можно ли написать на высокоуровневом языке несколько строк и получить работающий биндинг к тому же libav?
    ♡ recommended by @ndtimofeev, @qrilka, @juick

Replies (23)

  • @maxlapshin, а в целом, FFI почти нигде нормально не работает (имхо). Всюду свой геморрой.
  • @maxlapshin, Врятли можно чтоб несколько строк — это уж врятли , но в принципе github.com , допустим.
  • @maxlapshin, в хацкеле можно, работает не плохо, но нужно понимать особенности:
    вызывается так:

    foreign import ccall [un]safe "lib.h function" c_function :: тип

    unsafe — быстрее но блочит капабилити в RTS, и нельзя из ffi вызывать хацкельные колбеки.

    safe — медленнее, но не блочит рантайм и можно звать колбеки.

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

    ещё можно вызывать ffi из cmm кода, нужно для хаков стека (примеры в gmp напр.).

    ещё можно делать foreign primop (совсем без оверхеда, но запарно).
  • @6Volt, ага, т.е. к годной ffi прикладывается парсер сишных хедеров
  • @maxlapshin, не видел еще чтоб парсер приклаыдвался O_O тем более, что зачастую есть что-нить типа msdn
  • @maxlapshin, ещё в хацкеле есть hs2hsc и c2hs, которые помогают писать и портировать структурам.
  • @datacompboy, а ты посмотри на примеры. Везде пропихивается .h файл с декларацией типов
  • @maxlapshin, Через cdef , да(но это не самый валидный путь).
  • @6Volt, docs.python.org
    "To find out the correct calling convention you have to look into the C header file or the documentation for the function you want to call."
    парзера нет =)
  • @datacompboy, как это нет? А как оно само смотрит в хедер без парсера?
  • @maxlapshin, Оно ВООБЩЕ не смотрит в хедер!
    Вручную ты ему сам рассказываешь, что тебе надо:
    >> printf = libc.printf
    >> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
    >> printf("String '%s', Int %d, Double %f\n", "Hi", 10, 2.2)
  • @datacompboy, FFI дефакто обычно без парсера хэдеров идет (в лиспах луа питонах во всяком случае) . да и я не о питонах.
  • @maxlapshin, как работает: ghc.haskell.org
  • @qnikst, а это как конкретно реализовано: haskell.org . тебя вообще юзерсайд или как оно внутри интересует?
  • @maxlapshin, Покопался в старом коде — нашел примерчег (он нехороший, но иллюстрирует yadi.sk (ну или вот github.com
  • @6Volt, внутри тоже интересно, но там я так понимаю, хайтек бывает
  • @maxlapshin, если ответ мне, то могу вечером пару статей коротких скинуть.
  • @maxlapshin, хайтек бываетНе совсем понял .
    Но в общем — даже если хэдер парсится аргументы всёравно нужно руками печатать (А значит хэдеры читать придется самому). имена констант и функций импортируются на ура (но не всегда валидно). Я уже второй месяц пытаюсь привести Luajit-tcp-server(в коде я неочень , а там выше упомянутым ffi обвязанно всё ровным счётом причём в форме адского быдлокода) в удобоваримый вид — и всякий раз хочу повешатся .
  • @maxlapshin, luajit ffi: пропускаем хидеры через настоящий препроцессор (gcc например или clang), потом еще проходимся скриптиком (завернуть "константы" в енум, вырезать неподдерживаемое), и прямо кормим в ffi.cdef() (внутри там парсер, да)

    если кусок с вызовами компилится житом, то вызовы инлайнятся как есть, и получается нативная производительность. но за этим надо следить в спец-отладчике, есть множество условий, которые абортят компиляцию
    но, собсно, и интерпретация очень быстрая (+ беспроблемные места он компилит когда может)
    подводные камни конечно есть (например, коллбэки, вызывающиеся не на месте, не компилятся и требуют ручного отключения жита для вызывающего участка), но при поставленном процессе добавление либы в ffi выглядит именно как добавить строчку в билд. если конечно либа сделана без фимоза типа макросов (привет libev), коллбеков мозга или pass-by-value (привет старый libuv), иначе приходится городить обертки.

    кстати вроде есть готовые github.com но, как обычно, тухлятина
    wiki.luajit.org
    но мне лично удобнее прикручивать биндинги вышеозвученным способом, юзать нужные свежие версии и собирать на каждой платформе, писал так игру, например (к производительности пока никаких претензий, уперся в дрочево opengl; разве что проблемы с вектор-матешей, но это решаемо)
  • @fillest, результат выглядит, как и должен — без лишней хуйни дергаем прям функции, типы конвертятся почти прозрачно. вот пример luajit.org
    есть даже такое wiki.luajit.org
  • @fillest, ух ты. луа мне всё больше и больше нравится.
  • @datacompboy, ванильный луа и luajit отличаются .
    Luajit быстрее, имеет искаробочную либу для байтоёбства и ffi +у него малость большее число инструкций вмки.