使用haskell构建动态库并从C ++中使用它 [英] Building a dynamic library with haskell and using it from C++

查看:552
本文介绍了使用haskell构建动态库并从C ++中使用它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个包含haskell函数的动态库。我在linux上工作,想从C ++代码调用这个动态库。



我使用 http://wiki.python.org/moin/PythonVsHaskell ,并具有以下文件:



Test.hs:

  { - #LANGUAGE ForeignFunctionInterface# - } 
模块测试其中

import Foreign.C.Types

hsfun :: CInt - > IO CInt
hsfun x = do
putStrLnHello World
return(42 + x)

外部导出ccall
hsfun :: CInt - ; IO CInt

module_init.c:

  #define CAT(a,b)XCAT(a,b)
#define XCAT(a,b)a ## b
#define STR (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)
{
/ *这似乎是一个无操作,但它使GHCRTS envvar工作。 * /
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]编译测试(Test.hs,Test.o)
链接libTest.so ...

这会创建文件Test_stub.h:

  #includeHsFFI.h
#ifdef __cplusplus
externC{
#endif
extern HsInt32 hsfun(HsInt32 a1);
#ifdef __cplusplus
}
#endif

和Test_stub。 c:

  #define IN_STG_CODE 0 
#includeRts.h
#include h
#ifdef __cplusplus
externC{
#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:

  #includeTest_stub.h

#include< iostream>

using namespace std;

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

并希望编译和链接。但是当我调用g ++,它说:

  $ g ++ -I / usr / lib / ghc-7.0.3 / L. -lTest main.cpp 
/tmp/ccFP2AuB.o:在函数`main'中:
main.cpp :(。text + 0xa):undefined对`hsfun'的引用
collect2:ld gab 1 als Ende-Statuszurü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:在函数`hsfun'中:
Test_stub.c :(。text + 0x9):未定义对`rts_lock'的引用
Test_stub.c (。text + 0x16):未定义引用`rts_mkInt32'
Test_stub.c :(。+ 0x1d):未定义的引用`Test_zdfhsfunzua165_closure'
Test_stub.c :(。未定义的引用`rts_apply'
Test_stub.c :(。text + 0x2f):未定义引用`base_GHCziTopHandler_runIO_closure'
Test_stub.c :( .text + 0x3a):未定义`rts_apply'引用
Test_stub.c :(。text + 0x4a):未定义的引用`rts_evalIO'
Test_stub.c :(。text + 0x5c):未定义的引用`rts_checkSchedStatus'
Test_stub.c :(。
test_stub.c :(。text + 0x70):未定义的引用`rts_unlock'
Test_stub.o:在函数`stginit_export_Test_zdfhsfunzua165'中:
Test_stub.c :( .text.startup + 0x3):未定义的引用`Test_zdfhsfunzua165_closure'
Test_stub.c :( .text.startup + 0x8):未定义引用`getStablePtr'
collect2:ld gab 1 als Ende-Statuszurück

我必须链接Test_stub.o吗?如果是,为什么?

解决方案

可能比g ++更容易让ghc做工作, p>


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


在创建共享库之后为我完成了这项工作。我已经测试了它与7.2.2和7.0.2,都在这里工作。


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

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

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:

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

#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++ -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:

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

解决方案

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

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.

这篇关于使用haskell构建动态库并从C ++中使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆