目前,我正在用C写一个应用程序++,发现它的一些功能将得到更好的写在Haskell。我已经看到了从C代码中调用哈斯克尔说明,但有可能做同样的用C ++?

修改:要澄清,我正在寻找的是编译Haskell代码到一个外部库克++可以与来自C ++目标代码链接的方式

更新:我已经提出了一个工作下面的例子为别人兴趣(也因此,我不会忘了)

有帮助吗?

解决方案

编辑:您也应该看到下面托梅尔的答案。在这里,我的答案描述发生了什么事情的理论,但我可能有一些执行细节不完整的,而他的回答是一个完整的工作的例子。

作为sclv指示,编译应该没有问题。有可能的困难被链接的C ++代码,在这里你将有越来越所有连接所需的运行时库困难的一点。问题是,Haskell程序需要与Haskell的运行时库链接,和C ++方案需要与C ++运行时库链接。在Wiki页面你参考,当他们这样做

$ ghc -optc -O test.c A.o A_stub.o -o test

编译C程序中,实际执行两个步骤:它编译C程序到一个目标文件,然后链接在一起它。写出来,那会是这样的(也许并不完全正确,因为我不说话GHC):

$ ghc -c -optc-O test.c -o test.o
$ ghc test.o A.o A_stub.o -o test

GHC只是就像GCC(和,IIUC,功能就是 GCC)编译C程序时。当链接它,但是,它是从,如果你直接调用GCC,会发生什么,因为它也奇迹般地包括Haskell的运行时库不同。 G ++的工作方式相同为C ++程序 - 当它用作接头,它包括C ++运行时库

因此,正如我所说,你需要一种方法来编译既运行时库链接。如果在详细模式运行G ++编译和链接程序,像这样:

$ g++ test.cpp -o test -v

它会创建的输出什么它做一个长长的清单;在端部将是一个行输出的地方进行链接(与collect2子程序)指示哪些库它链接到。你可以把它与输出编译一个简单的C程序,看看什么是C ++的不同;在我的系统,它增加了-lstdc++

因此,你应该能够编译和链接您的混合的Haskell / C ++程序,像这样:

$ ghc -c -XForeignFunctionInterface -O A.hs     # compile Haskell object file.
$ g++ -c -O test.cpp                            # compile C++ object file.
$ ghc A.o A_stub.o test.o -lstdc++ -o test      # link

有,因为你已经指定-lstdc++,它将包括C ++运行时库(假设-l是正确的语法GHC,你需要检查),因为你已经与ghc链接,它将包含哈斯克尔运行时库。这应导致一个工作程序。

另外,你应该能够做到类似于GHC的-v输出调查的东西,并找出什么Haskell的运行时库(或库),它链接到Haskell的支持,然后链接使用C程序时添加库++ ,就像你已经为纯C ++程序做。 (见托默的答案那细节,因为这就是他所做的。)

其他提示

给有兴趣的人,这是测试的情况下,我终于得到了工作:


M.hs

module Foo where

foreign export ccall foo :: Int -> Int

foo :: Int -> Int
foo = floor . sqrt . fromIntegral

TEST.CPP

#include <iostream>
#include "M_stub.h"

int main(int argc, char *argv[])
{
    std::cout << "hello\n";
    hs_init(&argc, &argv);
    std::cout << foo(500) << "\n";
    hs_exit();
    return 0;
}

我做的编译和链接我的Windows机器上。到运行的命令(在该顺序):

>ghc -XForeignFunctionInterface -c M.hs
>g++ -c test.cpp -I"c:\Program Files\Haskell Platform\2010.2.0.0\lib\include"
>g++ -o test.exe -DDONT_WANT_WIN32_DLL_SUPPORT M.o M_stub.o test.o -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\haskell98-1.0.1.1" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\random-1.0.0.2" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\time-1.1.4" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\process-1.0.1.3" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\directory-1.0.1.1" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\old-time-1.0.0.5" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\old-locale-1.0.0.2" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\filepath-1.1.0.4" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\Win32-2.2.0.2" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\bytestring-0.9.1.7" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\array-0.3.0.1" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\base-4.2.0.2" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\integer-gmp-0.2.0.1" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib\ghc-prim-0.2.0.0" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib" -L"C:\Program Files\Haskell Platform\2010.2.0.0\lib/gcc-lib" -lHSrtsmain -lHShaskell98-1.0.1.1 -lHSrandom-1.0.0.2 -lHStime-1.1.4 -lHSprocess-1.0.1.3 -lHSdirectory-1.0.1.1 -lHSold-time-1.0.0.5 -lHSold-locale-1.0.0.2 -lHSfilepath-1.1.0.4 -lHSWin32-2.2.0.2 -luser32 -lgdi32 -lwinmm -ladvapi32 -lshell32 -lshfolder -lHSbytestring-0.9.1.7 -lHSarray-0.3.0.1 -lHSbase-4.2.0.2 -lwsock32 -luser32 -lshell32 -lHSinteger-gmp-0.2.0.1 -lHSghc-prim-0.2.0.0 -lHSrts -lm -lwsock32 -u _ghczmprim_GHCziTypes_Izh_static_info -u _ghczmprim_GHCziTypes_Czh_static_info -u _ghczmprim_GHCziTypes_Fzh_static_info -u _ghczmprim_GHCziTypes_Dzh_static_info -u _base_GHCziPtr_Ptr_static_info -u _base_GHCziWord_Wzh_static_info -u _base_GHCziInt_I8zh_static_info -u _base_GHCziInt_I16zh_static_info -u _base_GHCziInt_I32zh_static_info -u _base_GHCziInt_I64zh_static_info -u _base_GHCziWord_W8zh_static_info -u _base_GHCziWord_W16zh_static_info -u _base_GHCziWord_W32zh_static_info -u _base_GHCziWord_W64zh_static_info -u _base_GHCziStable_StablePtr_static_info -u _ghczmprim_GHCziTypes_Izh_con_info -u _ghczmprim_GHCziTypes_Czh_con_info -u _ghczmprim_GHCziTypes_Fzh_con_info -u _ghczmprim_GHCziTypes_Dzh_con_info -u _base_GHCziPtr_Ptr_con_info -u _base_GHCziPtr_FunPtr_con_info -u _base_GHCziStable_StablePtr_con_info -u _ghczmprim_GHCziBool_False_closure -u _ghczmprim_GHCziBool_True_closure -u _base_GHCziPack_unpackCString_closure -u _base_GHCziIOziException_stackOverflow_closure -u _base_GHCziIOziException_heapOverflow_closure -u _base_ControlziExceptionziBase_nonTermination_closure -u _base_GHCziIOziException_blockedIndefinitelyOnMVar_closure -u _base_GHCziIOziException_blockedIndefinitelyOnSTM_closure -u _base_ControlziExceptionziBase_nestedAtomically_closure -u _base_GHCziWeak_runFinalizzerBatch_closure -u _base_GHCziTopHandler_runIO_closure -u _base_GHCziTopHandler_runNonIO_closure -u _base_GHCziConc_ensureIOManagerIsRunning_closure -u _base_GHCziConc_runSparks_closure -u _base_GHCziConc_runHandlers_closure -lHSffi

的参数的最后克的一长串++命令是从运行

>ghc M.hs -v

和然后复制它说:“***接头:”命令。(一些第一参数的需要被去除)


其结果是:

>test
hello
22

这是关于这一主题的教程:

https://github.com/jarrett/cpphs

它涵盖了在C中调用的Haskell ++和从Haskell中调用C

因为你可以从调用C Haskell中,没有任何理由,你不能从C中将其++。调用从Haskell的C ++,在另一方面,是更难,并且通常需要C的包装。

编辑扩大。该指令是错误的不完整的。他们是一个维基页面。 HTTP:直接在GHC手册看// www.haskell.org/ghc/docs/6.12.2/html/users_guide/ffi-ghc.html

本介绍如何导出功能,以及如何使用自己的主。注意它说:“其他一些语言,比如C”。它说,这是因为你可以从可调用的香草C函数,你出口任何语言(和编译器)做到这一点,那HsFFI.h提供。这是语言无关,与编译器无关。它所需要的是能够使用调用系统上的标准调用约定的C函数,其中C ++编译器(如克++)的确提供。

小集团2.0添加了“外商库”功能,这似乎解决了连接问题,以及使整个构建过程多,一般更加愉快。

我把一个短实例教程的https:// github上。 COM / PDLLA /哈斯克尔-FFI-小集团-外国库实例

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top