Hi all, I am just starting to experiment with FFI, and am running into a problem. I was to create an FFI to the lgamma(3) found in many of the newer libm implementations. My code follows the sig. The lgamma function works. The gamma function core dumps (I am using ghc 5.04.3) on me. gdb reports a SIGSEGV in signgam(), but I'm not sure why. I believe that I need to use the monad because signgam is only valid after lgamma returns. Does anyone have an idea what I am doing wrong? Thanks. -- Matthew Donadio <m.p.donadio@ieee.org>
module Gamma (gamma, lgamma) where
import System.IO.Unsafe
foreign import ccall "math.h lgamma" lgammaC :: Double -> IO Double foreign import ccall "math.h signgam" signgamC :: IO Int
lgamma :: Double -> Double lgamma x = unsafePerformIO $ lgammaC x
gamma :: Double -> Double gamma x = unsafePerformIO $ gammaIO x
gammaIO :: Double -> IO Double gammaIO x = do lg <- lgammaC x s <- signgamC return $ fromIntegral s * exp lg
Matthew Donadio wrote:
I am just starting to experiment with FFI, and am running into a problem. I was to create an FFI to the lgamma(3) found in many of the newer libm implementations. My code follows the sig.
The lgamma function works. The gamma function core dumps (I am using ghc 5.04.3) on me. gdb reports a SIGSEGV in signgam(), but I'm not sure why. I believe that I need to use the monad because signgam is only valid after lgamma returns.
Does anyone have an idea what I am doing wrong?
Thanks.
-- Matthew Donadio <m.p.donadio@ieee.org>
module Gamma (gamma, lgamma) where
import System.IO.Unsafe
foreign import ccall "math.h lgamma" lgammaC :: Double -> IO Double foreign import ccall "math.h signgam" signgamC :: IO Int
signgam is an "int" variable, but this assumes that it is a function of type "int signgam(void)". Write a C wrapper "int get_signgam(void) { return signgam; }" and import that. -- Glynn Clements <glynn.clements@virgin.net>
foreign import ccall "math.h signgam" signgamC :: IO Int
signgam is an "int" variable, but this assumes that it is a function of type "int signgam(void)".
Write a C wrapper "int get_signgam(void) { return signgam; }" and import that.
Or alternatively, foreign import the address of the int and read it directly with 'peek'. import Foreign ... foreign import ccall "math.h &signgam" signgamC :: Ptr Int32 ... gammaIO :: Double -> IO Double gammaIO x = do lg <- lgammaC x s <- peek signgamC return $ fromIntegral s * exp lg Regards, Malcolm
Malcolm Wallace wrote:
foreign import ccall "math.h signgam" signgamC :: IO Int
signgam is an "int" variable, but this assumes that it is a function of type "int signgam(void)".
Write a C wrapper "int get_signgam(void) { return signgam; }" and import that.
Or alternatively, foreign import the address of the int and read it directly with 'peek'.
import Foreign ... foreign import ccall "math.h &signgam" signgamC :: Ptr Int32 ... gammaIO :: Double -> IO Double gammaIO x = do lg <- lgammaC x s <- peek signgamC return $ fromIntegral s * exp lg
One potential drawback with that approach is that an implementation might decide to add thread-safety, in the same manner as glibc does with errno: # if !defined _LIBC || defined _LIBC_REENTRANT /* When using threads, errno is a per-thread value. */ # define errno (*__errno_location ()) # endif [where __errno_location() returns a thread-specific location via pthread_getspecific().] OTOH, a C wrapper will cope with whatever contortions the libc developers decide to use. -- Glynn Clements <glynn.clements@virgin.net>
Malcolm Wallace wrote:
foreign import ccall "math.h signgam" signgamC :: IO Int
signgam is an "int" variable, but this assumes that it is a function of type "int signgam(void)".
Write a C wrapper "int get_signgam(void) { return signgam; }" and import that.
Or alternatively, foreign import the address of the int and read it directly with 'peek'.
Thanks for the clarification. I went with the second option, and that works great. -- Matthew Donadio (m.p.donadio@ieee.org)
participants (3)
-
Glynn Clements -
Malcolm Wallace -
Matthew Donadio