
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
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
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

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

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