GHC / FFI: вызов модуля haskell, который импортирует библиотеки haskell из C - PullRequest
6 голосов
/ 11 января 2012

Давайте рассмотрим общий пример того, как функция haskell может быть вызвана из функции C:

Модуль Haskell:

{-# LANGUAGE ForeignFunctionInterface #-}

module Safe where

import Foreign.C.Types

fibonacci :: Int -> Int
fibonacci n = fibs !! n
    where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral

foreign export ccall fibonacci_hs :: CInt -> CInt

И модуль C:

#include <HsFFI.h>
#ifdef __GLASGOW_HASKELL__
#include "Safe_stub.h"
extern void __stginit_Safe(void);
#endif
#include <stdio.h>

int main(int argc, char *argv[]) {
   int i;
   hs_init(&argc, &argv);
#ifdef __GLASGOW_HASKELL__
   hs_add_root(__stginit_Safe);
#endif

   i = fibonacci_hs(42);
   printf("Fibonacci: %d\n", i);

   hs_exit();
   return 0;
}

Я компилирую и связываю это:

$ ghc -c -O Safe.hs
$ ghc test.c Safe.o Safe_stub.o -o test

Это нормально. Но что, если мне нужно импортировать какую-то библиотеку в модуль haskell? Например, если мне нужно использовать строки байтов, я должен добавить «import Data.Bytestring.Char8» (этот модуль взят за пример и не используется в коде):

{-# LANGUAGE ForeignFunctionInterface #-}

module Safe where

import Foreign.C.Types
import Data.Bytestring.Char8

fibonacci :: Int -> Int
fibonacci n = fibs !! n
    where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral

foreign export ccall fibonacci_hs :: CInt -> CInt

И это не нормально, сейчас я получаю сообщение об ошибке:

$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_'

Все, что я сейчас нашел по этой проблеме, это: ошибка в GHC и следующее changeset (более формальное описание ошибки)

Поскольку я использую ghc-6.12.3, эта функция уже реализована. Поэтому я понятия не имею, как решить проблему.

Может быть, было бы проще создать общую библиотеку и динамически связать ее с моим модулем C?

1 Ответ

4 голосов
/ 11 января 2012

Я не думаю, что ошибка связана. Вы пробовали использовать --make?

$ ghc -c -O Safe.hs
$ ghc --make test.c Safe.o Safe_stub.o -o test

Эти ошибки являются видами ошибок, которые вы использовали для получения 1 при связывании чистого кода Haskell с зависимостями пакетов без использования --make; GHC связывается в base по умолчанию, но если вы хотите что-то из другого пакета, который не работает.

Вы также можете попробовать указать пакеты явно, если вам нужен более «ручной» метод:

$ ghc -c -O Safe.hs
$ ghc -package bytestring test.c Safe.o Safe_stub.o -o test

1 Начиная с GHC 7, --make является значением по умолчанию.

...