Как получить адрес глобальной переменной C через FFI Haskell? - PullRequest
2 голосов
/ 30 апреля 2020

Например, в C у меня есть что-то вроде этого, объявленного:

extern char _binary_res_txt_start[];

Это пришло из этой команды:

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

Как я могу получить Ptr в Haskell что указывает там? Если бы это была функция, я бы сделал что-то вроде foreign import ccall "&exp" a_exp :: FunPtr (Double -> Double), но я не думаю, что это работает для переменных.

1 Ответ

1 голос
/ 30 апреля 2020

Синтаксис foreign import работает и для переменных, если вы используете &. Затем вы можете использовать peekCString или packCString, чтобы прочитать его (или peekCStringLen или packCStringLen, если это не так завершается нулем, но вы знаете его длину). Вот полный пример:

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 - вещь. См. Почему символ _size связанного двоичного файла работает правильно? для получения подробной информации об этом.

...