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

Как использовать DLL в проекте Haskell?

Я хотел бы использовать внешнюю библиотеку RDFox в проекте Haskell.

Контекст: Я работаю над Windows и Linux, как с 64 битами, используя GHC 7.10, так и stack. RDFox запрограммирован на С++. Общие библиотеки RDFox (.dll,.so) могут быть загружены с помощью оболочек Java и Python.

Цель: Я хотел бы повторно использовать скомпилированные библиотеки из RDFox (.dll,.so) в моем проекте в Haskell, поэтому мне нужно создать оболочку Haskell для RDFox.

Проблемы: Будучи относительно новым для Haskell, я с трудом знаю, с чего начать. Я нашел несколько страниц по теме (из Haskell wiki и StackOverflow), но рабочий процесс и конфигурация мне не понятны.

Вопросы: Я хотел бы знать:

  • Как настроить stack и cabal для использования внешней библиотеки, для создания на Windows или Linux (разные машины, один и тот же репозиторий).
  • Как настроить GHCi для интерактивного тестирования этой внешней библиотеки.
  • Является ли перевод оболочки Python на Haskell лучшим способом? Я бы хотел избежать анализа кода RDFox С++.
4b9b3361

Ответ 1

  • Вам нужно использовать extra-lib-dirs и extra-libraries в разделе executable вашего файла .cabal так:

    name:                 MyApp
    version:              0.1.0.0
    synopsis:
    homepage:
    author:               simon.bourne
    category:
    build-type:           Simple
    cabal-version:        >=1.10
    
    library
      exposed-modules:      HelloWorld
      build-depends:        base >= 4.7 && < 5
      hs-source-dirs:       src
      default-language:     Haskell2010
    
    executable MyApp
      main-is:              Main.hs
      extra-lib-dirs:       lib
      extra-libraries:      helloWorld
      build-depends:        base >= 4.7 && < 5,
                            MyApp
      hs-source-dirs:       app
    
    default-language: Haskell2010
    

    Поместите свою dll и .so в lib. Будьте осторожны, вы столкнетесь с проблемами порядка ссылок, если вы используете статическую библиотеку (.a вместо .so) в linux.

    См. этот для примера. Не обманывайте себя именем, так как он отлично работает с файлами .so.

  • stack ghci должен работать только при условии, что он может найти вашу библиотеку (LD_LIBRARY_PATH в Linux).

  • API C (упомянутый в комментариях к вашему вопросу) уже существует. Вам просто нужно написать сигнатуры FFI Haskell, например:

    foreign import ccall safe "helloWorld" c_helloWorld :: IO ()
    

    Я бы очень рекомендовал использовать safe ccalls и не переносить функции в unsafePerformIO.

    Если вам нужно передать непрозрачные структуры, вы можете изучить c2hs или hsc2hs, но я не думаю, что вам нужно будет. Подробнее см. question.

Ответ 2

Вам нужно создать C-экспортированную оболочку для С++ api и оболочки Haskell для FFI в C-экспортированную оболочку.

Маршалинг между С# и Haskell описан здесь: Вызов Haskell с С#

но он очень похож на маршалинг между С++ и Haskell

Например, создайте функцию экспорта С++:

extern "C" __declspec(dllexport) int __cdecl addFive(int number);

extern "C" __declspec(dllexport) int __cdecl addFive(int number)
{
    return number + 5;
}

В Haskell вам нужен код импорта:

foreign import ccall "addFive" addFive :: Int -> Int

Затем вы можете использовать addFive в Haskell как типичную функцию Haskell

Для составных типов данных (классов и структур) вам нужно создать аналог типа данных С++ в Haskell. Затем вам нужно описать, как типы данных маршала от С++ до Haskell и от Haskell до С++.

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