在为 Haskell 编写 FFI 代码时,需要某种“垫片”并不罕见,我鼓励您只编写一个辅助函数:
FILE* get_stderr() { return stderr; }
并使用它(请参阅此答案底部的示例)。
但是,通过使用 vanilla FFI 对静态指针的支持,我能够使以下最小示例正常工作——它不stderr
直接导入,而是导入指向指针的指针stderr
。这种导入是c2hs不直接支持的,所以接口代码很丑,而且我认为没有什么办法可以避免stderr
在IO monad中取指针值,不管你有没有用c2hs。
// file.h
#include <stdio.h>
void func(FILE*);
// file.c
#include "file.h"
void func(FILE *f) {
fputs("Output to stderr!\n", f);
}
// File.chs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign
#include "file.h"
{#pointer *FILE as File newtype#}
{#fun func as ^ { `File' } -> `()'#}
foreign import ccall "&stderr" stderr_ptr :: Ptr (Ptr File)
main :: IO ()
main = do stderr <- File <$> peek stderr_ptr
func stderr
作为比较,这个带有辅助函数的最小示例在 Haskell 级别看起来更清晰:
// file.h
#include <stdio.h>
void func(FILE*);
FILE* get_stderr(void);
// file.c
#include "file.h"
void func(FILE *f) {
fputs("Output to stderr!\n", f);
}
FILE* get_stderr(void) {return stderr; }
// File.chs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
#include "file.h"
{#pointer *FILE as File newtype#}
{#fun func as ^ { `File' } -> `()'#}
{#fun pure get_stderr as ^ {} -> `File'#}
main :: IO ()
main = func getStderr
请注意,在这两个示例中,我删除了您的fclose
终结器。您可能不希望 Haskell 武断地决定现在是关闭stderr
您的好时机。