2011-12-31 4 views
17

से उपयोग करना है, मैं हैकेल फ़ंक्शंस वाली गतिशील लाइब्रेरी बनाना चाहता हूं। मैं लिनक्स पर काम करता हूं और सी ++ कोड से इस गतिशील पुस्तकालय को कॉल करना चाहता हूं।हैकेल के साथ गतिशील लाइब्रेरी का निर्माण करना और इसे C++

मैं http://wiki.python.org/moin/PythonVsHaskell पर उदाहरण के लिए प्रयोग किया जाता है और निम्न फ़ाइलें:

Test.hs:

{-# LANGUAGE ForeignFunctionInterface #-} 
module Test where 

import Foreign.C.Types 

hsfun :: CInt -> IO CInt 
hsfun x = do 
    putStrLn "Hello World" 
    return (42 + x) 

foreign export ccall 
    hsfun :: CInt -> IO CInt 

module_init.c:

#define CAT(a,b) XCAT(a,b) 
#define XCAT(a,b) a ## b 
#define STR(a) XSTR(a) 
#define XSTR(a) #a 

#include <HsFFI.h> 

extern void CAT (__stginit_, MODULE) (void); 

static void library_init (void) __attribute__ ((constructor)); 
static void 
library_init (void) 
{ 
    /* This seems to be a no-op, but it makes the GHCRTS envvar work. */ 
    static char *argv[] = { STR (MODULE) ".so", 0 }, **argv_ = argv; 
    static int argc = 1; 

    hs_init (&argc, &argv_); 
    hs_add_root (CAT (__stginit_, MODULE)); 
} 

static void library_exit (void) __attribute__ ((destructor)); 
static void 
library_exit (void) 
{ 
    hs_exit(); 
} 

अब मैं एक गतिशील करने के लिए इस फ़ाइलें संकलन पुस्तकालय:

$ ghc -dynamic -shared -fPIC -optc '-DMODULE=Test' Test.hs module_init.c -o libTest.so 
[1 of 1] Compiling Test    (Test.hs, Test.o) 
Linking libTest.so ... 

यह अन्य बातों के अलावा बनाता है फ़ाइल Test_stub.h:

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

और Test_stub.c:

#include "Test_stub.h" 

#include <iostream> 

using namespace std; 

int main() 
{ 
    cout << hsfun(5); 
} 

और:

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

extern StgClosure Test_zdfhsfunzua165_closure; 
HsInt32 hsfun(HsInt32 a1) 
{ 
Capability *cap; 
HaskellObj ret; 
HsInt32 cret; 
cap = rts_lock(); 
cap=rts_evalIO(cap,rts_apply(cap,(HaskellObj)runIO_closure,rts_apply(cap,&Test_zdfhsfunzua165_closure,rts_mkInt32(cap,a1))) ,&ret); 
rts_checkSchedStatus("hsfun",cap); 
cret=rts_getInt32(ret); 
rts_unlock(cap); 
return cret; 
} 
static void stginit_export_Test_zdfhsfunzua165() __attribute__((constructor)); 
static void stginit_export_Test_zdfhsfunzua165() 
{getStablePtr((StgPtr) &Test_zdfhsfunzua165_closure);} 
#ifdef __cplusplus 
} 
#endif 

तो मैं एक cpp फ़ाइल main.cpp बनाने इसे संकलित करना और लिंक करना चाहते हैं। लेकिन मैं जब जी ++ कहते हैं, यह कहते हैं:

$ g++ -I/usr/lib/ghc-7.0.3/include -L. -lTest main.cpp 
/tmp/ccFP2AuB.o: In function `main': 
main.cpp:(.text+0xa): undefined reference to `hsfun' 
collect2: ld gab 1 als Ende-Status zurück 

तो मैं कमांड लाइन के लिए Test_stub.o फ़ाइल जोड़ी (हालांकि मुझे लगता है कि hsfun समारोह पहले से ही libTest.so जो -lTest के माध्यम से जोड़ा जाता है में परिभाषित किया जाना चाहिए । पैरामीटर मुझे लगता है कि नहीं है, मैं Test_stub.o निष्पादन में फाइल क्योंकि मैं गतिशील जोड़ने का उपयोग करने के लिए) चाहते हैं लिंक करना चाहिए, लेकिन यह भी काम नहीं करता:

$ g++ -I/usr/lib/ghc-7.0.3/include -L. -lTest main.cpp Test_stub.o 
Test_stub.o: In function `hsfun': 
Test_stub.c:(.text+0x9): undefined reference to `rts_lock' 
Test_stub.c:(.text+0x16): undefined reference to `rts_mkInt32' 
Test_stub.c:(.text+0x1d): undefined reference to `Test_zdfhsfunzua165_closure' 
Test_stub.c:(.text+0x28): undefined reference to `rts_apply' 
Test_stub.c:(.text+0x2f): undefined reference to `base_GHCziTopHandler_runIO_closure' 
Test_stub.c:(.text+0x3a): undefined reference to `rts_apply' 
Test_stub.c:(.text+0x4a): undefined reference to `rts_evalIO' 
Test_stub.c:(.text+0x5c): undefined reference to `rts_checkSchedStatus' 
Test_stub.c:(.text+0x66): undefined reference to `rts_getInt32' 
Test_stub.c:(.text+0x70): undefined reference to `rts_unlock' 
Test_stub.o: In function `stginit_export_Test_zdfhsfunzua165': 
Test_stub.c:(.text.startup+0x3): undefined reference to `Test_zdfhsfunzua165_closure' 
Test_stub.c:(.text.startup+0x8): undefined reference to `getStablePtr' 
collect2: ld gab 1 als Ende-Status zurück 

मैं Test_stub से जोड़ने के लिए है ओ? यदि हां, क्यों? और मैं किस तर्क को लिंकर को पास कर दूं?

+0

मुझे विवरण नहीं पता; लेकिन आपको निश्चित रूप से हास्केल रनटाइम को भी लिंक करना होगा (विशेष रूप से इसके कचरा कलेक्टर)। –

+1

"$ g ++ -I/usr/lib/ghc-7.0.3/include -L। -lTest main.cpp" शायद यह काम करता है अगर आप कमांड लाइन के अंत में लिंकर झंडे डालते हैं? –

+0

@ डैनियल: यह दूसरी बार है जब मैं किसी को अंत में लिंकर झंडे लगाने का सुझाव देता हूं, और पहली बार समस्या को हल करने लगती थी। यही कारण है कि? मैंने सोचा कि झंडे की स्थिति कोई फर्क नहीं पड़ता? – Xeo

उत्तर

9

शायद जी ++ GHC दे रहा है के साथ कुश्ती की तुलना में आसान काम है,

GHC main.cpp -ओ hithere -एल है। -lTest -lstdC++

आपके द्वारा किए गए साझा lib को बनाने के बाद मेरे लिए नौकरी की। मैंने इसे 7.2.2 और 7.0.2 के साथ परीक्षण किया है, दोनों यहां काम करते हैं।

+2

हैकेल इंटरफेस एक बड़ी परियोजना का एक मॉड्यूल है और मैं पूरे सी ++ प्रोजेक्ट को ghc के साथ संकलित नहीं करना चाहता हूं। – Heinzi

+0

यह समझ में आता है। आप आवश्यक लिंकर झंडे को कैप्चर करने का प्रयास कर सकते हैं, ghc को उच्च पर्याप्त वर्बोजिटी के साथ उदाहरण को संकलित करें और फ़ाइल में stderr को पुनर्निर्देशित करें।हालांकि, यह आपको एक-दूसरे से जुड़े सामानों की एक लंबी सूची देगा, हालांकि। –

+1

मुझे यह आपके समाधान का उपयोग करके काम कर रहा है। जब मैं पैरामीटर -v को ghc पास करता हूं, तो यह कमांड लाइन पर प्रयुक्त लिंकर पैरामीटर प्रिंट करता है। – Heinzi

संबंधित मुद्दे