Как скомпилировать ресурс в двоичный файл в Haskell? - PullRequest
24 голосов
/ 19 июня 2011

Скажем, у меня есть файл dictionary.txt, мне нужно прочитать его в карту и использовать в своей программе, как мне сделать этот файл dictionary.txt, содержащийся в скомпилированном exe-файле?

Ответы [ 4 ]

21 голосов
/ 19 июня 2011

Вам придется придумать свой собственный способ, чтобы поместить его в карту, но http://hackage.haskell.org/package/file-embed попадет в ваш скомпилированный двоичный файл.Мы используем его для встраивания шаблонов в некоторые наши веб-приложения.

14 голосов
/ 19 июня 2011

Вы можете хранить сериализованные типы данных как литералы байтовых строк. Вот пример:

Тем не менее, file-embed автоматизирует этот процесс, упрощая выполнение нетривиальных вложений.

Все подходы сводятся к представлению статических данных как литерала байтовой строки,

{-# LANGUAGE OverloadedStrings #-}

import Data.Binary
import qualified Data.Map as M
import qualified Data.ByteString.Char8 as S
import Data.ByteString.Lazy
import Codec.Compression.GZip

--
-- this is a gzip compressed literal bytestring, storing a binary-encoded Data.Map
--
mytable =
    "\US\139\b\NUL\NUL\NUL\NUL\NUL\NUL\ETXEN\
    \\219\SO\194 \f\197\224\188\196\CAN\227\US\
    \\224\171~\NAKc\GS4ce\161`\178\191\215(\176\
    \\190\180\167\231\210\n\241\171\203\191\ti\
    \\157\217\149\249< \ENQ\214\&9>\202\162\179a\
    \\132X\233\ESC=\231\215\164\SYN\157\DC2D\226*\
    \\146\174o\t\167\DLE\209\"i_\240\193\129\199<W\
    \\250nC\CAN\212\CAN\162J\160\141C\178\133\216;\
    \\\@4\144-W\203\209x\205\140\166\RS\163\237]9f\
    \\170\143\ACK\163g\223\STX\184\&7\rH\222\FSW\
    \\130\&7D\197\NUL\164\&0U\193\186\t\186o\
    \\228\180~\NUL\a6\249\137#\SOH\NUL\NUL"

main = print =<< M.lookup "ghc" m
    where
        -- build the table from the bytestring:
        m :: M.Map String (Maybe String)
        m = decode . decompress . fromChunks . return $ mytable
8 голосов
/ 19 июня 2011

Вы можете использовать пользовательский хук Makefile / Setup.hs и вызывать windres (если вы в Windows) или objcopy / elfrc (если вы в Linux) для компиляции ресурсов в COFF / ELF объекты, которые вы можете затем объединить с вашими объектными файлами Haskell, чтобы сформировать конечный исполняемый файл. Затем вы можете получить доступ к ресурсам, используя Haskell FFI следующим образом (не проверено):

-- We have an image resource called "_imgdata"
foreign import ccall "&" _imgdata :: CString 

-- Size of _imgdata is 405585 bytes.
imgdata :: CStringLen
imgdata = (_imgdata, 405585)

Это решение будет более эффективным, чем использование file-embed (без преобразования CString -> ByteString), но и более сложным.

Кроме того, мне также понадобилась поддержка файла ресурсов во время моей работы над cabal-install , поэтому он, вероятно, будет интегрирован в какую-то будущую версию Cabal (если я ее реализую).

7 голосов
/ 19 июня 2011

Я настоятельно рекомендую использовать Template Haskell здесь, чтобы загрузить файл и превратить его в тип данных Haskell. Он будет не только скомпилирован в окончательный двоичный файл, но и полностью оптимизирован.

...