Wrong size for int for callbacks into Haskell from foreign code
The following code produces different results on amd64 (64-bit little endian) and s390x (64-bit big endian).
foo.h:
typedef void(*hs_callback)(int x);
extern void function_in_c(hs_callback cb);
foo.c:
#include "foo.h"
void function_in_c(hs_callback cb)
{
int x = 10;
cb(x);
}
Foo.hs:
module Main(main) where
import Foreign
import Foreign.C
type HsCallback = CInt -> IO ()
foreign import ccall "foo.h function_in_c"
functionInC :: FunPtr HsCallback -> IO ()
foreign import ccall "wrapper"
wrap :: HsCallback -> IO (FunPtr HsCallback)
main = do
f <- wrap $ \x -> print x
functionInC f
freeHaskellFunPtr f
On amd64 the output is 10, but on s390x is 0. On both machines, sizeOf (undefined :: CInt) == sizeof(int) == 4
. When changing HsCallback
to:
type HsCallback = Int -> IO ()
both produce the same, correct result, but the above seems wrong, as sizeOf (undefined :: Int) == 8
.
This has been reproduced with both ghc-8.4 and ghc-8.2, and causes dbus to fail to build on s390x (https://github.com/rblaze/haskell-dbus/issues/26), as it relies on libxml-sax which contains the above (simplified) code.
Trac metadata
Trac field | Value |
---|---|
Version | 8.4.3 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler (FFI) |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |