Frage

Ich bin derzeit eine App in C ++ und fand das Schreiben, dass einige seiner Funktionalität wäre besser in Haskell geschrieben werden. Ich habe Anweisungen gesehen auf Haskell von C-Code nennen, aber ist es möglich, das gleiche zu tun mit C ++?

EDIT:. Um zu klären, was ich suche ist eine Möglichkeit, Haskell-Code in eine externe Bibliothek zu kompilieren, dass g ++ mit dem Objektcode von C ++ verknüpfen

UPDATE:. Ich habe ein funktionierendes Beispiel unten für alle anderen Interessierten setzen (auch so werde ich nicht vergessen)

War es hilfreich?

Lösung

Edit: Sie sollten auch Tomer Antwort siehe unten. Meine Antwort hier beschreibt die Theorie von dem, was vor sich geht, aber ich kann unvollständig einige der Einzelheiten der Ausführung haben, während seine Antwort ein komplettes Arbeitsbeispiel ist.

Wie SCLV gibt, sollte Kompilieren kein Problem sein. Die Schwierigkeit besteht wahrscheinlich ist, wird die Verknüpfung des C ++ Code, und hier finden Sie ein wenig Schwierigkeiten haben, mit in alle benötigten Laufzeitbibliotheken verknüpft bekommen. Das Problem ist, dass Haskell Programme mit den Haskell-Laufzeitbibliotheken verknüpft werden müssen, und C ++ Programme müssen mit den C ++ Laufzeitbibliotheken verknüpft werden. In der Wiki-Seite zu verweisen, wenn sie es tun

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

das C-Programm zu kompilieren, dass zwei Schritte tatsächlich tut: Es kompiliert das C-Programm in eine Objektdatei, und dann verbindet sie miteinander. Ausgeschrieben, das wäre so etwas wie (wahrscheinlich nicht ganz richtig, da ich nicht sprechen GHC) sein:

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

GHC verhält sich wie GCC (und IIUC, funktionell is GCC), wenn das C-Programm zu kompilieren. Wenn es verbindet, ist es jedoch anders aus, was passiert, wenn man direkt GCC nennen, weil es die Haskell-Laufzeitbibliotheken auf magische Weise enthält auch. G ++ funktioniert auf die gleiche Art und Weise für C ++ Programme -. Wenn es als Linker verwendet wird, ist es die C ++ Laufzeitbibliotheken enthält

So, wie ich bereits erwähnt, müssen Sie in einer Art und Weise kompilieren, dass Links mit beiden Laufzeitbibliotheken. Wenn Sie laufen G ++ im ausführlichen Modus zu kompilieren und zu verknüpfen, ein Programm, etwa so:

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

wird es eine lange Liste von Ausgabe schaffen, was er tut; am Ende wird eine Ausgabezeile, wo es die Verknüpfung funktioniert (mit dem collect2 Unterprogramm), das angibt, welche Bibliotheken es Links zu. Sie können, dass für die Erstellung eines einfachen C-Programm mit dem Ausgang zu vergleichen, um zu sehen, was für C ++ anders ist; auf meinem System, fügt es -lstdc++.

So sollten Sie in der Lage sein, zu kompilieren und verknüpfen Sie Ihr gemischte Haskell / C ++ Programm wie folgt:

$ 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

Es, da Sie -lstdc++ angegeben haben, wird es umfassen die C ++ Laufzeitbibliothek (unter der Annahme -l ist die richtige GHC Syntax, Sie werden überprüfen müssen), und weil Sie mit ghc verknüpft haben, wird es die Haskell umfassen Laufzeitbibliothek. Dies sollte in einem Arbeitsprogramm zur Folge hat.

Alternativ sollten Sie in der Lage sein, etwas ähnliches wie die -v Ausgangsuntersuchung mit GHC zu tun, und herauszufinden, was Haskell-Laufzeitbibliothek (oder Bibliotheken) es Links zu für Haskell Unterstützung, und dann diese Bibliothek hinzufügen, wenn Ihr Programm mit C verbindet ++ , so wie man bereits für reine C ++ Programme tun. (Siehe Tomer Antwort nach Einzelheiten jenes, denn das ist, was er tat.)

Andere Tipps

für alle Interessierten, das ist der Testfall, dass ich endlich habe arbeiten:


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;
}

Ich habe den compiliert & Verknüpfung auf meinem Windows-Rechner. Die Befehle auszuführen (in dieser Reihenfolge) sind:

>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

Die lange Liste der Parameter für die letzten g ++ Befehl vom Laufen

>ghc M.hs -v

und dann kopieren Sie den Befehl, wo es heißt „*** Linker:“. (Einige der ersten Parameter müssen entfernt werden)


Das Ergebnis:

>test
hello
22

Dies ist ein Tutorial zum Thema:

https://github.com/jarrett/cpphs

Es deckt Haskell von C ++ Aufruf und ruft C von Haskell.

Da Sie Haskell von C nennen kann, gibt es keinen Grund, warum Sie es nicht aus C ++ aufrufen können. Der Aufruf C ++ von Haskell, auf der anderen Seite, ist viel schwieriger und erfordert in der Regel einen C-Wrapper.

Bearbeiten zu erweitern. Die Anweisungen sind falsch unvollständig. Sie sind eine Wiki-Seite. Schauen Sie direkt an der GHC Handbuch: http: // www.haskell.org/ghc/docs/6.12.2/html/users_guide/ffi-ghc.html

Dies wird beschrieben, wie Funktionen exportieren, und wie Sie Ihre eigene Haupt verwenden. Hinweis, wo es heißt „eine andere Sprache, sagt C.“ Er sagt dies, weil Sie dies aus jeder Sprache tun können (und Compiler), die die Vanille-C-Funktionen aufrufen können, dass Sie exportieren, und dass HsFFI.h zur Verfügung stellt. Dies ist sprachunabhängig und Compiler Agnostiker. Alles was es braucht ist die Fähigkeit, invoke C-Funktionen der Standard-Aufrufkonventionen auf Ihrem System verwenden, das ein C ++ Compiler (wie g ++) sicher stellt.

Kabale 2.0 hinzugefügt die „foreign-Bibliothek“ -Funktion, die die Linker-Fragen sowie wodurch der gesamte Build-Prozess viel angenehmer im Allgemeinen zu lösen scheint.

Ich habe ein kurzes Tutorial mit Beispiel https: // GitHub. com / PDLLA / haskell-ffi-Kabalen-Fremd-library-Beispiele

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top