我在Mac OS中的/ usr / local / lib /下安装了库gsl(libgsl.dylib),并希望从Haskell调用库函数。但是我没有使用GHCi但是使用GHC成功了。
在GHCi中:
stack ghci --ghci-options="Bessel.hs -lgsl"
> besselJn 0 10
dyld: lazy symbol binding failed: Symbol not found: _gsl_sf_bessel_J0_e
Referenced from: libgsl.dylib
Expected in: flat namespace
dyld: Symbol not found: _gsl_sf_bessel_J0_e
Referenced from: libgsl.dylib
Expected in: flat namespace
在GHC中:
stack ghc -- Bessel-main.hs -lgsl
./Bessel-main (which is succeed)
Bessel.hs是一个包导出函数besselJn
,Bessel-main.hs
只是要调用的主模块。
我使用GHCi的方式有什么不对吗?很奇怪,GHC可以成功编译/链接共享库并运行,但GHCi不能。
添加更多信息。
Bessel.hs
使用命令Bessel.hsc
生成hsc2hs Bessel.hsc
(应首先使用stack install hsc2hs
安装hsc2hs)。以下是
Bessel.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
module Bessel (besselJn) where
import Foreign
import Foreign.Ptr
import Foreign.C.String
import Foreign.C.Types
import System.IO.Unsafe
#include <gsl/gsl_sf_result.h>
data GslSfResult = GslSfResult { gsl_value :: CDouble, gsl_error :: CDouble }
instance Storable GslSfResult where
sizeOf _ = (#size gsl_sf_result)
alignment _ = alignment (undefined :: CDouble)
peek ptr = do
value <- (#peek gsl_sf_result, val) ptr
error <- (#peek gsl_sf_result, err) ptr
return GslSfResult { gsl_value = value, gsl_error = error }
poke ptr (GslSfResult value error) = do
(#poke gsl_sf_result, val) ptr value
(#poke gsl_sf_result, err) ptr error
foreign import ccall unsafe "gsl/gsl_sf_bessel.h gsl_sf_bessel_Jn_e"
c_besselJn :: CInt -> CDouble -> Ptr GslSfResult -> IO CInt
foreign import ccall unsafe "gsl/gsl_errno.h gsl_set_error_handler_off"
c_deactivate_gsl_error_handler :: IO ()
foreign import ccall unsafe "gsl/gsl_errno.h gsl_strerror"
c_error_string :: CInt -> IO CString
besselJn :: Int -> Double -> Either String (Double, Double)
besselJn n x = unsafePerformIO $
alloca $ \gslSfPtr -> do
c_deactivate_gsl_error_handler
status <- c_besselJn (fromIntegral n) (realToFrac x) gslSfPtr
if status == 0
then do
GslSfResult val err <- peek gslSfPtr
return $ Right (realToFrac val, realToFrac err)
else do
error <- c_error_string status
error_message <- peekCString error
return $ Left ("GSL error: "++error_message)
贝塞尔main.hs
module Main where
import Bessel as B
main = do
print $ B.besselJn 0 10