2011-12-28 64 views
2

我想打電話給Haskell函數出來的C++並沒有使用教程在http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/ffi-ghc.html運用C++ Haskell的功能:未定義引用錯誤

所以我有一個Haskell文件Foo.hs:

module Foo where 

foreign export ccall foo :: Int -> IO Int 

foo :: Int -> IO Int 
foo n = return (length (f n)) 

f :: Int -> [Int] 
f 0 = [] 
f n = n:(f (n-1)) 

並呼籲

ghc Foo.hs 

它創造了一個Foo_stub.h:

#include "HsFFI.h" 
#ifdef __cplusplus 
extern "C" { 
#endif 
extern HsInt foo(HsInt a1); 
#ifdef __cplusplus 
} 
#endif 

一個Foo_stub.c:

#define IN_STG_CODE 0 
#include "Rts.h" 
#include "Stg.h" 
#ifdef __cplusplus 
extern "C" { 
#endif 

extern StgClosure Foo_zdffoozualy_closure; 
HsInt foo(HsInt a1) 
{ 
Capability *cap; 
HaskellObj ret; 
HsInt cret; 
cap = rts_lock(); 
cap=rts_evalIO(cap,rts_apply(cap,(HaskellObj)runIO_closure,rts_apply(cap, Foo_zdffoozualy_closure,rts_mkInt(cap,a1))) ,&ret); 
rts_checkSchedStatus("foo",cap); 
cret=rts_getInt(ret); 
rts_unlock(cap); 
return cret; 
} 
static void stginit_export_Foo_zdffoozualy() __attribute__((constructor)); 
static void stginit_export_Foo_zdffoozualy() 
{getStablePtr((StgPtr) &Foo_zdffoozualy_closure);} 
#ifdef __cplusplus 
} 
#endif 

這也造就了Foo_stub.o文件。

我現在創建了一個main.cpp的文件:

#include "Foo_stub.h" 
int main() 
{ 
    foo(3); 
} 

,並試圖對其進行編譯。

使用G ++失敗:

$ g++ -I/usr/lib/ghc-7.0.3/include/ main.cpp Foo_stub.o 
Foo_stub.o: In function `foo': 
Foo_stub.c:(.text+0xa): undefined reference to `rts_lock' 
Foo_stub.c:(.text+0x18): undefined reference to `rts_mkInt' 
Foo_stub.c:(.text+0x20): undefined reference to `Foo_zdffoozualy_closure' 
Foo_stub.c:(.text+0x28): undefined reference to `rts_apply' 
Foo_stub.c:(.text+0x30): undefined reference to `base_GHCziTopHandler_runIO_closure' 
Foo_stub.c:(.text+0x38): undefined reference to `rts_apply' 
Foo_stub.c:(.text+0x48): undefined reference to `rts_evalIO' 
Foo_stub.c:(.text+0x58): undefined reference to `rts_checkSchedStatus' 
Foo_stub.c:(.text+0x62): undefined reference to `rts_getInt' 
Foo_stub.c:(.text+0x6d): undefined reference to `rts_unlock' 
Foo_stub.o: In function `stginit_export_Foo_zdffoozualy': 
Foo_stub.c:(.text+0x80): undefined reference to `Foo_zdffoozualy_closure' 
Foo_stub.c:(.text+0x85): undefined reference to `getStablePtr' 
collect2: ld returned status 1 

所以我試圖GHC --make。但是這也失敗了:

$ ghc --make main.cpp Foo_stub.o 
cc1plus: Warning: Option »-Wimplicit« is valid for C/ObjC, but not for C++ [activated by default] 
Foo_stub.o: In function `foo': 
Foo_stub.c:(.text+0x20): undefined reference to `Foo_zdffoozualy_closure' 
Foo_stub.o: In function `stginit_export_Foo_zdffoozualy': 
Foo_stub.c:(.text+0x80): undefined reference to `Foo_zdffoozualy_closure' 
collect2: ld returned status 1 

我該如何編譯它?

回答

7

試試這個:

$ ghc --make -no-hs-main main.cpp Foo.hs 

我相信問題是GHC認爲你正在傳遞存根對象文件僅僅是另一個正常鏈接的對象,但你不能傳遞Foo.o文件本身,所以存根代碼沒有任何可鏈接的東西!直接傳入源文件應該可以解決它。 (這是基於文檔和你看到的錯誤上只是猜想,我沒有測試過。)

我覺得你可以做單獨的編譯是這樣的:

$ ghc --make Foo.hs 
$ ghc --make -no-hs-main main.cpp Foo.o 

,但我不確定。您可能還想考慮將您的Haskell代碼編譯爲shared library,然後通過g++將其鏈接到主程序。

-no-hs-main是當您的程序入口點不是Haskell值Main.main時需要的,如鏈接的文檔中所述。