56 votes

Appel de Haskell à partir de code C ++

Je suis en train d'écrire une application en C++ et a constaté que certaines de ses fonctionnalités serait mieux écrit en Haskell. J'ai vu des instructions sur l'appel de Haskell à partir de code C, mais est-il possible de faire la même chose avec le C++?

EDIT: Pour préciser, ce que je suis à la recherche d'un moyen de compiler du code Haskell dans une bibliothèque externe g++ pouvez lien avec l'objet de code C++.

Mise à JOUR: j'ai mis un exemple ci-dessous pour toute autre personne intéressée (aussi je ne l'oublierai pas).

61voto

Tomer Vromen Points 911

Pour toute personne intéressée, c'est le cas de test que j'ai enfin obtenu de travail:


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

J'ai fait la compile & reliant sur ma machine Windows. Les commandes à exécuter (dans cet ordre) sont les suivants:

>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

La longue liste de paramètres pour la dernière commande g++ est à partir de l'exécution

>ghc M.hs -v

et la copie de la commande où il est dit "***l'éditeur de liens:" (certains de la première paramètres doivent être supprimés).


Le résultat:

>test
hello
22

36voto

Brooks Moses Points 6205

Edit: Vous devriez également voir de Tomer réponse ci-dessous. Ma réponse ici décrit la théorie de ce qui se passe, mais j'ai peut-être quelques-uns des détails de l'exécution incomplète, alors que sa réponse est un exemple de travail.

Comme sclv l'indique, la compilation devrait y avoir aucun problème. La difficulté qu'il y a probablement un lien vers le code C++, et ici, vous aurez un peu de difficulté avec l'obtention de toutes les bibliothèques d'exécution liée. Le problème est que Haskell programmes doivent être liés avec le Haskell bibliothèques d'exécution, et les programmes C++ doivent être liés avec le C++ runtime des bibliothèques. Dans la page Wiki que vous référence, quand ils ne

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

pour compiler le programme en C, qui ne fait en deux étapes: Il compile le programme C dans un fichier objet, puis des liens ensemble. Écrit, qui serait quelque chose comme (probablement pas tout à fait le droit, car je ne parle pas de GHC):

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

GHC seulement des actes comme GCC (et, IIUC, fonctionnellement est GCC) lors de la compilation du programme C. Lors de la liaison, cependant, il est différent de ce qui se passe si vous appeler GCC directement, car elle aussi comme par magie comprend le Haskell bibliothèques d'exécution. G++ fonctionne de la même manière pour les programmes C++ -- quand il est utilisé comme un éditeur de liens, il comprend le C++ runtime des bibliothèques.

Donc, comme je l'ai mentionné, vous avez besoin de compiler de façon que les liens avec les deux bibliothèques. Si vous exécutez G++ en mode verbose pour compiler et lier un programme, comme suit:

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

il permettra de créer une longue liste de sortie sur ce qu'il fait; à la fin sera une ligne de sortie où il fait la liaison (avec l' collect2 sous-programme), indiquant que les bibliothèques des liens vers elle. Vous pouvez comparer cela à la sortie de la compilation d'un simple programme en C pour voir ce qui est différent de C++; sur mon système, il ajoute -lstdc++.

Donc, vous devriez être en mesure de compiler et lier votre mélange Haskell/C++ programme comme suit:

$ 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

Il y a, parce que vous avez spécifié -lstdc++, il inclut le C++ runtime library (en supposant -l est le droit de GHC syntaxe; vous aurez besoin de vérifier), et parce que vous avez lié avec ghc, il comprendra le Haskell bibliothèque d'exécution. Il devrait en résulter un programme de travail.

Alternativement, vous devriez être en mesure de faire quelque chose de similaire à l' -v sortie d'enquête GHC, et de comprendre ce Haskell bibliothèque d'exécution (ou bibliothèques), des liens vers elle pour Haskell, le soutien, et puis les ajouter à la bibliothèque lors de la liaison de votre programme C++, tout comme vous le faites déjà pour pure programmes C++. (Voir Tomer réponse pour les détails, puisque c'est ce qu'il a fait.)

9voto

Jarrett Points 2487

Après avoir lu les réponses ici et essayé des choses par moi-même, j'ai décidé d'écrire un tutoriel et un exemple:

https://github.com/jarrett/cpphs

Il couvre l'appel de Haskell à partir de C ++ et l'appel de C à partir de Haskell.

2voto

sclv Points 25335

Puisque vous pouvez appeler Haskell à partir de C, il n'y a aucune raison que vous ne pouvez l'appeler à partir de C++. L'appel de C++ à partir de Haskell, d'autre part, est beaucoup plus difficile et nécessite généralement un C wrapper.

Edit pour se développer. Les instructions sont mal à incomplète. Ils sont une page de wiki. Regarder directement le GHC manuel: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/ffi-ghc.html

Cela explique comment exporter des fonctions, et l'utilisation de votre propre main. Note de l'endroit où il est dit "une autre langue, dire C." Il dit cela parce que vous pouvez le faire à partir de n'importe quelle langue (et le compilateur) qui peuvent invoquer la vanille C fonctions que vous exportez, et que HsFFI.h fournit. C'est la langue agnostique, et le compilateur agnostique. Tout ce qu'il faut est la possibilité d'appeler des fonctions C en utilisant le standard de conventions d'appel sur votre système, qui est un compilateur C++ (tels que g++) fournit certainement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X