2012-01-11 7 views
6

Tomemos un ejemplo común de cómo una función Haskell puede llamar desde una función C:GHC/FFI: llamando al módulo de Haskell que importa bibliotecas Haskell C

Haskell módulo:

{-# 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 

y el módulo 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; 
} 

I de compilación y enlace que:

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

Eso está bien. Pero, ¿qué ocurre si necesito importar alguna biblioteca en el módulo haskell? Por ejemplo, si tengo que usar cadenas de bytes debo añadir "Data.Bytestring.Char8 importación" (este módulo se toma como ejemplo y no se utiliza en el código):

{-# 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 

Y eso no está bien, por ahora obtener un error:

$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_' 

Todo lo que he encontrado actualmente en el problema es el siguiente: a bug in GHC y de la siguiente changeset (more formal description of the bug)

como utilizo GHC-6.12.3, ya tengo esta característica implementada. Entonces no tengo idea de cómo solucionar el problema.

Quizás, sería más fácil crear una biblioteca compartida y vincularla dinámicamente con mi módulo C?

+1

El conjunto de cambios es más reciente que 6.12.3, por lo que aún tiene que llamar a 'hs_add_root' con 6.12. Ni siquiera llegó a 7.0. –

Respuesta

4

No creo que el error esté relacionado. ¿Has probado usando --make?

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

Esos errores son los tipos de errores que utiliza para obtener al vincular código Haskell puro con las dependencias de paquetes sin usar --make; GHC enlaces en base de forma predeterminada, pero si desea algo de otro paquete que no funciona.

También puede probar la especificación de los paquetes de forma explícita si desea un método más "manual":

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

Desde GHC 7, --make ha sido el defecto.

+0

Gracias, esto es exactamente lo que necesito, tan simple :) Y he perdido muchas horas tratando de vincularlo. – skvadrik

+0

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

+0

He actualizado mi respuesta con los comandos de trabajo :) – ehird