4

有一个相当低级的应用程序,我遇到了需要确定 Haskell 函数地址的情况。我可以用 FFI 来做到这一点,也就是 C,但我想直接在 Haskell 中做到这一点。

这是我目前使用 FFI 的解决方案:

main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Foreign
import Foreign.C.Types
import Text.Printf

foreign import ccall "getFuncAddr"
  getFuncAddr :: CULong

main :: IO ()
main = do
  printf "0x%016x\n" (fromIntegral getFuncAddr :: Word64)

foreign export ccall func :: IO ()
func :: IO ()
func = do
  printf "hello world\n"

ffi.c:

void func(void);

unsigned long getFuncAddr(void)
{
    return (unsigned long) func;
}

生成文件:

all: main
    ./$<
    objdump -D $< | grep '<func>'

main: main.hs ffi.c
    ghc --make -O2 $^ -o $@

与往常一样,也可作为gist使用。

4

2 回答 2

6

尝试这个:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where

import Foreign
import Foreign.C.Types
import Text.Printf

foreign import ccall "&func"
  funcaddr :: FunPtr (IO ())

main :: IO ()
main = do
  printf "0x%016x\n" (fromIntegral (ptrToIntPtr (castFunPtrToPtr funcaddr)) :: Int)

foreign export ccall func :: IO ()
func :: IO ()
func = do
  printf "hello world\n"

请参阅Haskell 2010 报告的这一部分,并查找“静态地址”。

于 2012-06-11T14:52:21.440 回答
2

我认为FunPtr的文档几乎可以满足您的需求。简短的版本是你使用foreign import "wrapper"的,如下:

foreign import ccall "wrapper"
  getFuncAddr :: IO () -> IO (FunPtr (IO ()))

然后如果您稍后完成它,请使用freeHaskellFunPtr.

于 2012-06-10T10:47:07.753 回答