如何在Haskell中将资源编译成二进制文件



假设我有一个dictionary.txt文件,我需要将其读取到映射中并在程序中使用,如何使这个dictionary.txt文件包含在编译的exe文件中?

您必须想出自己的方法将其放入Map中,但是http://hackage.haskell.org/package/file-embed会将其放入已编译的二进制文件中。我们使用它在一些web应用程序中嵌入模板。

您可以将序列化的数据类型存储为字节字符串文字。这里有一个例子:

  • http://code.haskell.org/~dons/code/编译的常量/
  • http://haskell.org/haskellwiki/Compiling_in_constants

然而,文件嵌入自动化了这一过程,使非琐碎的嵌入变得更容易。

所有的方法本质上都可以归结为将静态数据表示为字节字符串文字

{-# 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 =
    "US139bNULNULNULNULNULNULETXEN
    \219SO194 f197224188196CAN227US
    \224171~NAKcGS4ce161`178191215(176
    \190180167231210n241171203191ti
    \157217149249< ENQ214&9>202162179a
    \132X233ESC=231215164SYN157DC2D226*
    \146174ot167DLE209"i_240193129199<W
    \250nCCAN212CAN162J160141C178133216;
    \@4144-W203209x205140166RS163237]9f
    \170143ACK163g223STX184&7rH222FSW
    \130&7D197NUL164&0U193186t186o
    \228180~NULa6249137#SOHNULNUL"
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

您可以使用自定义Makefile/Setup.hs挂钩,并调用windres(如果您在Windows上)或objcopy/elfrc(如果您是在Linux上)将资源编译为COF/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)

该解决方案将比使用文件嵌入(不进行CString->ByteString转换)更高效,但也更复杂。

顺便说一句,在我安装cabal的工作中,我还需要资源文件支持,所以它可能会集成到cabal的未来版本中(如果我要实现的话)。

我强烈建议在这里使用Template Haskell来加载文件并将其转换为Haskell数据类型。它不仅会被编译成最终的二进制文件,而且会被充分优化。

相关内容

  • 没有找到相关文章

最新更新