2012-01-11 31 views
6

Chúng ta hãy ví dụ phổ biến như thế nào một hàm Haskell có thể được gọi từ một hàm C:GHC/FFI: gọi mô-đun Haskell đó nhập khẩu các thư viện Haskell từ C

Haskell mô-đun:

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

Và mô-đun 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; 
} 

tôi biên dịch và liên kết nó:

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

OK. Nhưng nếu tôi cần nhập một số thư viện trong mô-đun haskell thì sao? Ví dụ, nếu tôi cần phải sử dụng bytestrings tôi nên thêm "Data.Bytestring.Char8 nhập khẩu" (mô-đun này được thực hiện cho một ví dụ và không được sử dụng trong mã):

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

Và đó không phải là ok, bây giờ tôi nhận được một lỗi:

$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_' 

Tất cả tôi đã tìm thấy trên hiện vấn đề là thế này: a bug in GHC và như sau changeset (more formal description of the bug)

như tôi đã sử dụng GHC-6.12.3, tôi đã có tính năng này thực hiện. Vì vậy, tôi không có ý tưởng làm thế nào để khắc phục vấn đề.

Có thể sẽ dễ dàng hơn khi tạo thư viện được chia sẻ và liên kết động với thư viện C của tôi?

+1

Thay đổi mới hơn 6.12.3, vì vậy bạn vẫn phải gọi 'hs_add_root' với 6.12. Nó thậm chí không làm cho nó thành 7,0. –

Trả lời

4

Tôi không nghĩ rằng lỗi đó có liên quan. Bạn đã thử sử dụng --make chưa?

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

Những lỗi được các loại lỗi mà bạn sử dụng để có được khi liên kết mã Haskell tinh khiết với gói phụ thuộc mà không sử dụng --make; GHC liên kết trong base theo mặc định, nhưng nếu bạn muốn bất cứ điều gì từ gói khác không hoạt động.

Bạn cũng có thể thử xác định các gói một cách rõ ràng nếu bạn muốn có một phương pháp "thủ công" hơn:

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

Kể từ GHC 7, --make đã được mặc định.

+0

Cảm ơn bạn, đây chính xác là những gì tôi cần, đơn giản :) Và tôi đã lãng phí nhiều giờ cố gắng liên kết nó. – skvadrik

+0

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

+0

Tôi đã cập nhật câu trả lời của mình với các lệnh làm việc :) – ehird

Các vấn đề liên quan