【问题标题】:How do I get the address of a C global variable through the Haskell FFI?如何通过 Haskell FFI 获取 C 全局变量的地址?
【发布时间】:2020-04-30 13:53:54
【问题描述】:

例如,在 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) 的事情,但我认为这不适用于变量。

【问题讨论】:

  • 您是否真的需要出于某种原因从实际的.o 文件加载数据,或者只是您希望最终将数据硬烘焙到可执行文件中?在这种情况下,会有更好的路线。
  • 我需要来自目标文件的数据
  • 有一种方法可以从目标文件foreign import ccall "&exp" a_exp :: FunPtr (Double -> Double)链接函数,但是如何链接数据块?
  • @mxvd 我将您的评论纳入问题中,并尝试简化以达到其核心。让我知道我是否正确解释了所有内容。

标签: haskell import ffi object-files


【解决方案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?

【讨论】:

  • `不在范围内:类型构造函数或类'CChar'`在哪里可以找到它?
  • import GHC.Ptr import Foreign.C.Types foreign import ccall safe "static &amp;_binary_res_txt_start" txt_start :: Ptr СChar foreign import ccall safe "static &amp;_binary_res_txt_size" txt_size :: Ptr Int 现在如何在屏幕上显示文本? UTF-8 putStrLnprint 中的文本如何从地址中获取字符串?
  • @mxvd 见我回答的最后一句话。 peekCStringLen 来自 Foreign.C.String 可以做到这一点。
  • @mxvd 我刚刚添加了一个完整的示例。
猜你喜欢
  • 1970-01-01
  • 2019-10-07
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多