2012-04-26 9 views
6

有沒有像Windows上的System.Posix?如何使用haskell處理窗口上的信號?

我想下面的代碼在Windows上運行,我應該改變它?

import IO 
import Control.Exception hiding (catch) 
import Control.Concurrent 
import Network 
import System.Posix ---cannot be run on windows. 

main = withSocketsDo (installHandler sigPIPE Ignore Nothing >> main') 
    --so the signal handler cannot be used 

main' = listenOn (PortNumber 9900) >>= acceptConnections 

acceptConnections sock = do 
     putStrLn "trying to accept" -- debug msg 
     [email protected](h,host,port) <- accept sock 
     print conn -- debug msg 
     forkIO $ catch (talk conn `finally` hClose h) (\e -> print e) 
     acceptConnections sock 

talk [email protected](h,_,_) = hGetLine h >>= hPutStrLn h >> hFlush h >> talk conn 

例如,如果我想在程序退出時,CTRL + C,我必須在C++中添加一個處理SIGINT,所以,寫一些像這樣的代碼:

void callback(int sig) 
{ 
    // printf("catch\n"); 
} 
... 
signal(SIGINT,callback); 

但我不不知道如何在哈斯克爾做到這一點,使用FFI?

回答

4
import Foreign 
import Foreign.C.Types 

type Handler = CInt->IO() 
foreign import ccall "wrapper" 
    genHandler:: (Handler) -> IO (FunPtr Handler) 

foreign import ccall safe "signal.h signal" 
     install:: CInt->FunPtr Handler->IO CInt 
main=do 
     s<-genHandler (\x->putStrLn $ "catch "++(show x)) 
     res<- install 2 s 
     putStrLn $ show res 
     s<-getLine 

上面的代碼是我想做的事,只是導入signal功能,用一個Haskell回調。

3

我不是Windows專家,所以我不知道你需要做的就不理你選擇忽略此事件的任何東西。您可能想要在Win32文檔中找到您安裝的任何版本。但是,我對構建系統以及如何獲取構建函數的兩個版本中的一個有所瞭解。因此,該戰略將是這樣的:

  1. 讓兩個目錄,unix-srcWin32-src(或類似名稱)。
  2. 在每個目錄下,把含有這樣的一個模塊OSCompat(或類似名稱):

    -- unix-src/OSCompat.hs 
    module OSCompat where 
    import System.Posix 
    ignorePipe = installHandler sigPIPE Ignore Nothing 
    
    -- Win32-src/OSCompat.hs 
    module OSCompat where 
    import System.Win32 
    ignorePipe = -- ??? 
    
  3. 在你project.cabal文件,把類似的東西在你的executable塊以下幾點:

    if os(windows) 
        build-depends: Win32 
        hs-source-dirs: Win32-src 
    else 
        build-depends: unix 
        hs-source-dirs: unix-src 
    
  4. 更改頂層模塊看起來像這樣:

    import OSCompat 
    main = withSocketsDo (ignorePipe >> main') 
    
1

我不認爲你可以做這樣的事情在Windows上。 Windows不是Posix兼容的,所以它不完全支持信號,例如,它does not support發送信號到其他進程。信號的數量還有is pretty limited

如果我理解正確你忽略SIGPIPE來保護你的程序,如果它的輸出由管道輸送到另一個進程,然後將該進程終止時,右退出?對不起,我不知道如何在Windows做到這一點(事實上你不經常看到程序通過簡單的管連接在Windows上)。 如果你的信號處理與插座連接,this可能會有幫助。