Вопрос

В настоящее время я пишу приложение на C ++ и обнаружил, что некоторые из его функциональных возможностей лучше было бы написать на Haskell.Я видел инструкции по вызов Haskell из C-кода, но возможно ли сделать то же самое с C ++?

Редактировать: Чтобы уточнить, я ищу способ скомпилировать код Haskell во внешнюю библиотеку, которую g ++ может связать с объектным кодом из C ++.

Обновить: Я привел рабочий пример ниже для всех, кто еще заинтересован (также, чтобы я не забыл).

Это было полезно?

Решение

Редактировать: Вы также должны увидеть ответ Thamer ниже. Мой ответ здесь описывает теорию того, что происходит, но у меня могут быть некоторые детали выполнения неполных, тогда как его ответ является полным рабочим примером.

Поскольку 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 ++ в Verbose Mode для компиляции и ссылки программа, как так:

$ 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, Он будет включать в себя библиотеку Runtime Runtime. Это должно привести к рабочей программе.

Поочередно, вы должны быть в состоянии сделать что-то похожее на -v Исходное исследование с GHC, и выясните, какая библиотека Runtime Runtime (или библиотеки) ссылается на поддержку Haskell, а затем добавить эту библиотеку при связывании вашей программы с помощью C ++, так же, как вы уже делаете для чистых программ C ++. (См. Ответ Thamer для деталей этого, поскольку это то, что он сделал.)

Другие советы

Для всех заинтересованных, это тестовый случай, который я наконец получил работу:


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

Долгий список параметров для последней команды G ++ от работает

>ghc M.hs -v

И затем копирование команды, где она говорит «*** Синкер:» (Некоторые из первых параметров необходимо удалить).


Результат:

>test
hello
22

Это учебник по теме:

https://github.com/jarrett/cpphs.

Он охватывает призыв HASKELL от C ++ и позвонить в CaSkell.

Поскольку вы можете назвать Haskell из C, нет причин, по которой вы не можете назвать его от C ++. Вызов C ++ из HASKELL, с другой стороны, намного сложнее и обычно требует конперпера.

Редактировать для расширения. Инструкции ошибаются неполными. Это страница вики. Посмотрите непосредственно в руководстве GHC: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/fhistchc.html.

Это описывает, как экспортировать функции и как использовать свой собственный основной. Обратите внимание, где он говорит «какой-то другой язык, скажем, C». Это говорит об этом, потому что вы можете сделать это с любого языка (и компилятора), который может вызвать функции Vanilla C, которые вы экспортируете, и что HSFFI.h обеспечивает. Это язык агностики и компилятор агностики. Все это требует, - это возможность вызывать функции C с использованием стандартных конвенций вызова в вашей системе, какой компилятор C ++ (например, G ++), безусловно, обеспечивает.

cabal 2.0 добавила функцию "внешняя библиотека", которая, по-видимому, решает проблемы с компоновщиком, а также делает весь процесс сборки намного приятнее в целом.

Я собрал краткий примерный учебник https://github.com/pdlla/haskell-ffi-cabal-foreign-library-examples

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top