से उपयोग करना है, मैं हैकेल फ़ंक्शंस वाली गतिशील लाइब्रेरी बनाना चाहता हूं। मैं लिनक्स पर काम करता हूं और सी ++ कोड से इस गतिशील पुस्तकालय को कॉल करना चाहता हूं।हैकेल के साथ गतिशील लाइब्रेरी का निर्माण करना और इसे 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 से जोड़ने के लिए है ओ? यदि हां, क्यों? और मैं किस तर्क को लिंकर को पास कर दूं?
मुझे विवरण नहीं पता; लेकिन आपको निश्चित रूप से हास्केल रनटाइम को भी लिंक करना होगा (विशेष रूप से इसके कचरा कलेक्टर)। –
"$ g ++ -I/usr/lib/ghc-7.0.3/include -L। -lTest main.cpp" शायद यह काम करता है अगर आप कमांड लाइन के अंत में लिंकर झंडे डालते हैं? –
@ डैनियल: यह दूसरी बार है जब मैं किसी को अंत में लिंकर झंडे लगाने का सुझाव देता हूं, और पहली बार समस्या को हल करने लगती थी। यही कारण है कि? मैंने सोचा कि झंडे की स्थिति कोई फर्क नहीं पड़ता? – Xeo