如果我用 C 语言编写它,我可能会给它一个这样的原型:
void assemble(char **out, size_t *outlen, const char *in);
这转化为这样的东西(未经测试):
import qualified Assemble -- your module with the "assemble" function
import Foreign.Ptr (Ptr)
import Foreign.Storable (poke)
import Foreign.Marshal.Utils (copyBytes)
import Foreign.Marshal.Alloc (mallocBytes)
import Foreign.C.Types (CSize, CChar)
import Foreign.C.String (CString, peekCString)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
foreign export ccall assemble :: Ptr (Ptr CChar) -> Ptr CSize -> CString -> IO ()
assemble :: Ptr (Ptr CChar) -> Ptr CSize -> String -> IO ()
assemble out outlen instrptr = do
instr <- peekCString instrptr
unsafeUseAsCStringLen (Assemble.assemble instr) $ \(p, n) -> do
outval <- mallocBytes n
copyBytes outval p n
poke out outval
poke outlen (fromIntegral n)
这会将数据复制到一个malloc
区域,这很好,因为它是“安全的”,并且 C 代码不需要做任何特殊的事情来释放它(除了free()
)。