在 haskell 的 FFI 后面使用 stdout/stderr/stdin 流

发布于 2024-08-14 19:20:56 字数 472 浏览 8 评论 0原文

我正在开发一个小型 haskell 程序,该程序使用我用 C++ 开发的外部静态库。它通过ghc的FFI(外部函数接口)来访问lib。在这个库中,我想对控制台进行一些输出。然而,在我看来,C++ 方面没有正确的 stdout 处理,因为输出不会出现在控制台上。那么,我的问题是:

  • ghc 是否劫持了这三个流(stdout、stdin、stderr),或者 libstdc++ 是否只是因为我与 ghc 链接而没有初始化它们?
  • 如果我的 FFI 导入写入标准输出,它们是否需要“安全”?
  • 如何将 stdout 传递给 C 函数?我应该直接传递它还是需要 C 类型?

附加说明:我将 libstdc++ 直接链接到可执行文件(即 ghc -lstdc++ ...),我天真地认为这是执行此操作的正确方法。看起来效果很好

免责声明:对于 Haskell 来说还是很陌生,所以现在还只是一小步;P

I'm developing a small haskell program that uses an external static library I've developed in C++. It accesses the lib through ghc's FFI (foreign function interface). Inside this library I would like to do some output to the console. However, it looks to me like the c++ side of things does not have a correct handle to stdout because output does not appear on the console. So then, my questions are:

  • Does ghc hijack these three streams (stdout, stdin, stderr) or is libstdc++ simply not initializing them because I'm linking with ghc?
  • Do my FFI imports need to be "safe" if they write to stdout?
  • How can I pass stdout to a C function? Should I simply pass it directly or do I need a C type?

Additional notes: I'm linking libstdc++ directly to the executable (i.e. ghc -lstdc++ ...) which I naively assumed would be the correct way of doing this. Seems to work well

Disclaimer: Still pretty new to Haskell, so baby steps for now ;P

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽你眉间 2024-08-21 19:20:57

您的问题似乎是 libstdc++ 没有被初始化。我不完全确定为什么 - -lstdc++ 在我的系统上就足够了 - 但看看它是否能以相反的方式工作。

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++

Your problem does appear to be that libstdc++ is not being initialized. I'm not entirely sure why — -lstdc++ is sufficient on my system — but see if it works the other way around.

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

Compiling:

$ 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++
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文