Использование потоков stdout / stderr / stdin за FFI haskell - PullRequest
5 голосов
/ 17 декабря 2009

Я разрабатываю небольшую программу на Haskell, которая использует внешнюю статическую библиотеку, которую я разработал на C ++. Он обращается к библиотеке через FFI (интерфейс внешней функции) ghc. Внутри этой библиотеки я хотел бы сделать вывод на консоль. Тем не менее, он выглядит для меня как то, что сторона c ++ не имеет правильного дескриптора stdout, потому что вывод не отображается на консоли. Итак, мои вопросы:

  • ghc захватывает эти три потока (stdout, stdin, stderr) или libstdc ++ просто не инициализирует их, потому что я связываюсь с ghc?
  • Должен ли мой импорт FFI быть "безопасным", если он пишет в стандартный вывод?
  • Как я могу передать стандартный вывод в функцию C? Должен ли я просто передать его напрямую или мне нужен тип C?

Дополнительные примечания: Я связываю libstdc ++ напрямую с исполняемым файлом (т.е. ghc -lstdc ++ ...), который, как я наивно полагал, будет правильным способом сделать это. Кажется, хорошо работает

Отказ от ответственности: Все еще довольно плохо знаком с Хаскеллом, так что, малышка, пока что, P

1 Ответ

4 голосов
/ 17 декабря 2009

Ваша проблема заключается в том, что libstdc ++ не инициализируется. Я не совсем уверен, почему & mdash; -lstdc++ достаточно в моей системе & mdash; но посмотрите, работает ли это наоборот.

Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
foreign export ccall "Main_main" main :: IO ()
foreign import ccall driver_callback :: IO ()
main = putStrLn "Now in Haskell" >> driver_callback

driver.cc

#include <iostream>

extern "C" {
# include "HsFFI.h"

#  ifdef __GLASGOW_HASKELL__
#   include "Main_stub.h"
    extern void __stginit_Main(void);
#  endif

    void driver_callback(void) {
        std::cout << "Back in C++" << std::endl;
    }
}

int main(int argc, char **argv) {
    hs_init(&argc, &argv);
# ifdef __GLASGOW_HASKELL__
    hs_add_root(__stginit_Main);
# endif

    std::cout << "Starting in C++" << std::endl;

    Main_main();

    hs_exit();
    return 0;
}

Компиляция:

$ ghc -c --make Main
[1 of 1] Compiling Main             ( Main.hs, Main.o )
$ ghc --make -no-hs-main -lstdc++ Main driver.cc
Linking Main ...
$ ./Main
Starting in C++
Now in Haskell
Back in C++
...