如何通过Haskell FFI获取C全局变量的地址?

时间:2020-04-30 13:53:54

标签: haskell import ffi object-files

例如,在C语言中,我有这样的声明:

extern char _binary_res_txt_start[];

它来自以下命令:

ld -r -b binary -o binary.o res.txt

如何在Haskell中获得指向此处的Ptr?如果它是一个函数,我会做类似foreign import ccall "&exp" a_exp :: FunPtr (Double -> Double)的事情,但我认为这不适用于变量。

1 个答案:

答案 0 :(得分:1)

foreign import语法也适用于变量,只要您使用&。然后,您可以使用peekCStringpackCString来读取它(或peekCStringLenpackCStringLen,如果它不是以空值结尾但知道它的长度)。这是一个完整的示例:

printf 'foo\0bar' > res.txt
ld -r -b binary -o binary.o res.txt
extern char _binary_res_txt_start[];
extern char _binary_res_txt_end[];
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr

foreign import ccall "&_binary_res_txt_start" txt_start :: Ptr CChar
foreign import ccall "&_binary_res_txt_end" txt_end :: Ptr CChar

main = do
  str <- peekCStringLen (txt_start, txt_end `minusPtr` txt_start)
  print str
"foo\NULbar"

请注意,尽管ld -b binary还会产生一个_binary_res_txt_size符号,但是ASLR是一件事,它不再有用。有关详细信息,请参见Why doesn't a linked binary file's _size symbol work correctly?