我正在为Haskell中的动态编程语言构建解释器。我想添加一个简单的机制来调用C函数。在过去,我使用Haskell FFI调用我已明确声明其名称和类型的C函数;这种方法在这里不起作用,因为解释器不会知道要在运行时调用的C函数的名称或类型。
是否可以在运行时声明和调用C函数?我应该从哪里开始?
答案 0 :(得分:8)
如果可以列出可能调用的C函数的所有可能类型,则可以使用FFI的动态导入功能(http://www.haskell.org/onlinereport/haskell2010/haskellch8.html)。动态导入函数在运行时包装C函数。您需要为您可能正在调用的每个C函数类型声明一个导入函数。 (实际上,只有ABI很重要,因此您可以将所有C指针类型视为等效类型。)
foreign import ccall "dynamic" mkPtrFun :: FunPtr (Ptr () -> IO (Ptr ())) -> Ptr () -> IO (Ptr ())
如果你有一个指向C函数的指针,你可以使用这个包装函数从Haskell调用它。
callWithNull :: FunPtr (Ptr a -> IO (Ptr ())) -> IO (Ptr ())
callWithNull f = mkPtrFun f nullPtr
如果在编译Haskell代码时C函数的类型未知,则不能使用FFI执行此操作。
对于动态获取C函数指针,FFI对您没有帮助。您可以在C中使用动态加载库,例如libdl。请参见手册页:http://linux.die.net/man/3/dlopen。