실험을 마친 후 g_input_stream_read
이라는 자체 구현을 작성했습니다. 그것은 아주 예쁜 아니다조차 안전하지 않을 수도 있지만,이 성공적으로 메인의 상단에 지정된 파일의 첫 번째 1,024 문자를 출력합니다 :
import Control.Monad (liftM)
import Data.Char (chr)
import Data.Word (Word8)
import Foreign
import Foreign.C (CInt)
import System.GIO
import System.GIO.Types (unInputStream, toInputStream)
import System.Glib (glibTypeInit, GError)
foreign import ccall unsafe "g_input_stream_read"
-- inputStreamRead <stream> <buffer> <count> <cancellable> <error>, returns the number of bytes read
inputStreamRead :: Ptr InputStream -> Ptr a -> CInt -> Ptr (Maybe Cancellable) -> Ptr GError -> IO (CInt)
addrToChar :: Ptr a -> Int -> IO (Char)
addrToChar p i = do
let addr = p `plusPtr` i
val <- peek addr :: IO Word8
return $ chr (fromIntegral val)
main :: IO()
main = do
glibTypeInit
let file = fileFromParseName "file.txt"
fileInputStream <- fileRead file Nothing
let stream = unInputStream $ toInputStream fileInputStream
allocaBytes 1024 $ \buffer -> do
alloca $ \err -> do
bytesRead <- liftM fromEnum $ inputStreamRead (unsafeForeignPtrToPtr stream) buffer 1024 nullPtr err :: IO Int
result <- mapM (addrToChar buffer) [0..bytesRead]
putStrLn result
그것은 간단한 inputStreamRead :: InputStream -> IO (String)
가되기 위해 몇 가지 작업을 요구하지만, 적어도 그것은 올바른 방향으로 나아가는 단계입니다.
EDIT : 더 나은 해결책을 찾았습니다. 바이트 수를 읽을 때까지 독서를 유지해야이 사람은 0에 해당하고, 우호적 엔트리 포인트가 있습니다
import Control.Monad (liftM)
import Data.Char (chr)
import Data.Word (Word8)
import Foreign
import Foreign.C (CInt)
import System.GIO
import System.GIO.Types
import System.Glib (glibTypeInit, GError)
foreign import ccall unsafe "g_input_stream_read"
-- inputStreamRead <stream> <buffer> <count> <cancellable> <error>, returns the number of bytes read
inputStreamRead :: Ptr InputStream -> Ptr a -> CInt -> Ptr Cancellable -> Ptr GError -> IO (CInt)
chunk :: Int
chunk = 4096
bytesToText :: [Word8] -> [Char]
bytesToText [] = []
bytesToText (x:xs) = (chr $ fromEnum x):(bytesToText xs)
readGIOStream :: InputStream -> Maybe Cancellable -> IO ([Word8])
readGIOStream stream cancel = do
allocaBytes chunk $ \buffer -> do
alloca $ \err -> do
case cancel of
Just c -> withForeignPtr (unCancellable c) $ \c' -> readChunk buffer c' err streamPtr
Nothing -> readChunk buffer nullPtr err streamPtr
where streamPtr = unInputStream stream
readChunk b c e s = withForeignPtr s $ \s' -> do
bytesRead <- liftM fromEnum $ inputStreamRead s' b (toEnum chunk) c e
result <- mapM (\i -> peek $ b `plusPtr` i) [0..(bytesRead-1)]
if bytesRead == 0
then return result
else do rest <- readChunk b c e s
return $ result ++ rest
main :: IO()
main = do
glibTypeInit
let file = fileFromParseName "live-forever.txt"
fileInputStream <- fileRead file Nothing
text <- liftM bytesToText $ readGIOStream (toInputStream fileInputStream) Nothing
putStrLn text
'g_type_init'은 [여기]를 볼 수 있습니다 (http://hackage.haskell.org/packages/archive/를 glib/latest/doc/html/System-Glib-GType.html # v : glibTypeInit) (질문의 나머지 부분은 확실하지 않지만). –
....하지만 .... 왜? – AndrewC
입력 스트림을 작성하는 방법을 제공하고 읽는 방법이 아닌 것은 이해할 수 없습니다. – damien