Подтвердить что ты не робот

Возможно ли встроить Haskell в библиотеку C непрозрачно?

то есть. возможно ли внедрить код Haskell в библиотеку C, чтобы пользователь библиотеки не знал, что Haskell используется? В частности, чтобы пользователь мог использовать несколько библиотек, которые вставляют Haskell без каких-либо конфликтов?

Насколько я понимаю, вы встраиваете между вызовами hs_init и hs_exit, но они связаны с глобальными хаотическими состояниями и должны противоречить другим вызовам, no?

4b9b3361

Ответ 1

Да, это возможно, чтобы вызвать код Haskell с C (и наоборот) через FFI, Интерфейс внешних функций. К сожалению, как говорит haskell.org docs, вы не можете избежать вызовов для инициализации и завершения среды haskell:

Вызов hs_init() инициализирует систему времени выполнения GHC. НЕ пытайтесь вызывать любые функции Haskell перед вызовом hs_init(): плохие вещи будут несомненно, произойдет.

Но, this также интересен:

В hs_init() может быть несколько вызовов, но каждый из них должен быть сопоставляемый одним (и только одним) вызовом hs_exit()

И более того:

Спецификация FFI требует, чтобы реализация поддерживала повторную инициализацию сам после закрытия с помощью hs_exit(), но GHC не в настоящее время поддерживают это.

В принципе, моя идея состоит в том, что вы можете использовать эти спецификации, чтобы написать себе класс С++ для оболочки, который управляет вызовами hs_init и hs_exit для вас, например, с помощью методов шаблонов, окруженных hs_init и hs_exit, который вы можете переопределить, используя любой вызов haskell, который вы хотите. Однако будьте осторожны с взаимодействием с другими библиотеками, вызывающими код haskell: вложенные уровни вызовов на hs_init и hs_exit должны быть в порядке (чтобы было безопасно использовать библиотеки, которые называет их между вашими обертками), но общее количество вызовов должно всегда совпадают, что означает, что если эти библиотеки только инициализируют среду, не пытаясь ее закрыть, то вам нужно закончить работу.

Еще одна (возможно лучшая) идея, не использующая наследование и переопределение, может состоять из простого класса HaskellEnv, который вызывает hs_init в конструкторе и hs_exit в деструкторе. Если вы объявите их как автоматические переменные, вы получите, что вызовы hs_init и hs_exit будут всегда совпадать, и последний вызов hs_exit будет выполнен, как только будет уничтожен последний объект HaskellEnv когда вы покидаете его сферу действия. Посмотрите этот вопрос, чтобы предотвратить создание объектов в куче (они могут быть опасны в этом случае).