使用haskell構建動態庫並使用C ++實現它

[英]Building a dynamic library with haskell and using it from C++


I want to build a dynamic library containing haskell functions. I work on linux and want to call this dynamic library from C++ code.

我想構建一個包含haskell函數的動態庫。我在linux上工作,想從C ++代碼調用這個動態庫。

I used the example at http://wiki.python.org/moin/PythonVsHaskell and have the following files:

我在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 ();
}

Now I compile this files to a dynamic library:

現在我將這些文件編譯為動態庫:

$ 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 ...

This creates among other things the file Test_stub.h:

這創建了文件Test_stub.h:

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

and Test_stub.c:

#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

Then I create a cpp file main.cpp:

然后我創建一個cpp文件main.cpp:

#include "Test_stub.h"

#include <iostream>

using namespace std;

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

and want to compile and link it. But when I call g++, it says:

並希望編譯和鏈接它。但是當我打電話給g ++時,它說:

$ 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

So I added the Test_stub.o file to the command line (although I think the hsfun function should already be defined in libTest.so which is added via the -lTest parameter. I don't think, I should link the Test_stub.o file into the executable because I want to use dynamic linking), but this also doesn't work:

所以我將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

Do I have to link the Test_stub.o? If yes, why? And which arguments should I pass to the linker?

我是否必須鏈接Test_stub.o?如果是,為什么?我應該將哪些參數傳遞給鏈接器?

1 个解决方案

#1


9  

Probably easier than wrestling with g++ is letting ghc do the work,

可能比用g ++摔跤更容易讓ghc做這項工作,

ghc main.cpp -o hithere -L. -lTest -lstdc++

ghc main.cpp -o hithere -L。 -lTest -lstdc ++

did the job for me after creating the shared lib the way you did. I have tested it with 7.2.2 and 7.0.2, both worked here.

在按照你的方式創建共享庫后,為我完成了這項工作。我用7.2.2和7.0.2對它進行了測試,兩者都在這里工作。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2011/12/31/725fe9d68a04645ce470b7867fbd08b0.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com