我的代码:
getGPS :: String -> IO (Double, Double)
getGPS ip = do
html <- getHTML ip
let ztags =Prelude.zip [0..] . filterStr . getTagText . getTags $ html
let nlat = Prelude.head $ Prelude.map fst . Prelude.filter (\(_, str) -> strEq str ("Latitude:" :: String)) $ ztags
let nlng = Prelude.head $ Prelude.map fst . Prelude.filter (\(_, str) -> strEq str ("Longitude:" :: String)) $ ztags
let lat = read (Prelude.head $ Prelude.map snd . Prelude.filter (\(n, _) -> n == nlat + 1) $ ztags) :: Double
let lng = read (Prelude.head $ Prelude.map snd . Prelude.filter (\(n, _) -> n == nlng + 1) $ ztags) :: Double
return (lat, lng)
工作正常。现在,我想通过FFI
导出此功能,以便从C应用程序访问它。我做了foreign export ccall getGPS :: CString -> IO (CDouble, CDouble)
,但这不起作用:
GPS.hs:45:1:
Illegal foreign declaration: requires unregisterised, llvm (-fllvm) or native code generation (-fasm)
When checking declaration:
foreign export ccall "getGPS" getGPS
:: CString -> IO (CDouble, CDouble)
GPS.hs:45:1:
Unacceptable result type in foreign declaration:
‘(CDouble, CDouble)’ cannot be marshalled in a foreign call
When checking declaration:
foreign export ccall "getGPS" getGPS
:: CString -> IO (CDouble, CDouble)
GPS.hs:45:1:
Couldn't match type ‘Double’ with ‘CDouble’
Expected type: CString -> IO (CDouble, CDouble)
Actual type: String -> IO (Double, Double)
In the expression: getGPS
When checking declaration:
foreign export ccall "getGPS" getGPS
:: CString -> IO (CDouble, CDouble)
Failed, modules loaded: none.
如何正确导出此功能?
答案 0 :(得分:7)
实际上有两个错误:
foreign export
和getGPS
函数的类型必须匹配,因此您需要从CString到CDouble的GPS包装器(使用peekCString
和CDouble
来转换它们)Ptr CDouble
个参数或定义结构。所以可能的解决方案是
foreign export ccall "getGPS" getGPS' :: CString -> Ptr CDouble -> Ptr CDouble -> IO ()
getGPS' :: CString -> Ptr CDouble -> Ptr CDouble -> IO ()
getGPS' str d1 d2 = do
(r1, r2) <- getGPS =<< peekCString str
poke d1 (CDouble r1)
poke d2 (CDouble r2)
使用C代码时,请务必致电hs_init
和hs_exit
。