如何通过C FFI将Haskell数据作为不透明数据类型传递?

时间:2016-09-30 13:32:14

标签: haskell ffi

我试图通过一个不读取或修改该数据的C库传递一些数据。

foreign import ccall "lua.h lua_pushlightuserdata"
  c_lua_pushlightuserdata :: LuaState -> Ptr a -> IO ()

foreign import ccall "lua.h lua_touserdata"
  c_lua_touserdata :: LuaState -> CInt -> IO (Ptr a)

data MyData =
  MyData
  { dataIds = TVar [Int]
  , dataSomethingElse = [String]
  }

calledFromRunLuaState :: LuaState -> IO ()
calledFromRunLuaState luaState = do
  dataPtr <- c_lua_touserdata luaState (-1)
  myData <- dataFromPtr dataPtr
  doSomethingWith myData

main = do
  luaState <- Lua.newstate
  ids <- atomically $ newTVar []
  c_lua_pushlightuserdata luaState (dataToPtr (MyData ids []))
  runLuaState luaState

我试图找出如何定义dataFromPtrdataToPtr

1 个答案:

答案 0 :(得分:4)

这是StablePtr的用途。因此,您必须使用newStablePtr代替dataFromPtrdeRefStablePtr代替dataToPtr。请注意,deRefStablePtrIO monad中运行,因此您必须相应地调整代码。此外,您必须调整外部导入以使用稳定指针,例如:

foreign import ccall "lua.h lua_pushlightuserdata"
  c_lua_pushlightuserdata :: LuaState -> StablePtr MyData -> IO ()

,同样适用于lua_touserdata

最后,当您使用newStablePtr创建稳定指针时,垃圾收集器不会自动释放该值。因此,您有责任通过致电freeStablePtr来解除分配。