2017-09-16 47 views
0

我想國外進口一些C頭的功能,但如何處理其定義爲類型FILE *的標準錯誤:Haskell如何使用extern FILE * from c?

extern FILE* __stderrp; 
#define stderr __stderrp 

也許不準確。我用c2hs我FFI工作,並已具備:

{#pointer *FILE as File foreign finalizer fclose newtype#} 

,但我無法導入標準錯誤是這樣的:

foreign import ccall "stdio.h stderr" stderr :: File 

我的C函數簽名:

void func(FILE*); 

我可以用c2hs導入func:

{#fun func as^{`File'} -> `()'#} 

我需要使用stderr來運行func:

func(stderr); 

我是noob的外國進口機制。看來我不能用這種方式導入stderr。

ps。也許我會包裝我的func在一個新的功能

void func2(void){func(stderr);} 

這是一個解決方法,但似乎不乾淨。

+0

什麼問題?也可以用'foreign import'導入它。 – arrowd

回答

1

這是不尋常的要求某種類型的「墊片」 Haskell的編寫FFI代碼時,我會鼓勵你只是寫一個輔助函數:

FILE* get_stderr() { return stderr; } 

和使用(見例如在這個答案的底部)。

不過,我能得到下面的小例子,通過使用靜態指針香草FFI的支持工作 - 它不直接導入stderr,但進口的指針stderr指針。這種導入並不直接被c2hs支持,所以接口代碼很難看,我不認爲有什麼辦法可以避免在IO單元中獲取stderr指針的值,而不管你是否使用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 

爲了比較,具有輔助功能的這個小例子,着眼於哈斯克爾水平更清潔:

// 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的好時機。

+0

好吧,** getStderr >> = func **是我需要的另一種解決方法,但我認爲保留終結器並在c函數中執行骯髒的工作會更好。我的意思是,我不需要從c導入stderr,因爲它似乎是一個變量存在於** linkage **(extern FILE * __stderrp),而不僅僅是一個普通的c常量,我的意思是我不能使用像** stderr = {#const stderr#} ** – uuhan

0

隨着0.28.2版本c2hs,下面的代碼工作:

-- lib.chs 
{#pointer *FILE as File newtype#} 
foreign import ccall "stdio.h &__stderrp" c_stderr :: Ptr (Ptr File) -- can not just use "stdio.h &stderr", this may cause a reference error 

-- main.hs 
stderr <- File <$> peek c_stderr 
func stderr