0

It seems like a bug in NLFFI SML/NJ implementation. C function is

void f0
    ( short a0
    , short a1

and so on

    , short a7
    ) {
    printf ("a0 == %hx\n", a0);
    printf ("a1 == %hx\n", a1);

and so on

    printf ("a7 == %hx\n", a7);
}

I compile it by

gcc -shared -fPIC -m32 -o libdelme.so _.c

and install. Invocation from C

f0 (0x7654, 0x3210, 0x9876, 0x5432, 0x1234, 0x5678, 0x9012, 0x3456);

prints correct values, and invocation from ML

F_f0.f' (0x7654, 0x3210, 0x9876, 0x5432, 0x1234, 0x5678, 0x9012, 0x3456);

prints this

a0 == 7654
a1 == 9876
a2 == 1234
a3 == 9012
a4 == 0
a5 == 1800
a6 == 3cf0
a7 == ee00

A similar effect is with signed char. It seems that my C library is expecting arguments aligned to 2^5-bit address and NLFFI does not align them.

I was encountered this error when creating a binding to XCB, so I can't change its header files, function prototypes and such. Everything is already prepared in my Linux distribution.

Maybe it is related that I cross-compile, i.e. compile to x86 code on AMD64.

SML/NJ version

$ pacman -Q smlnj
smlnj 110.77-1
beroal
  • 369
  • 4
  • 14

2 Answers2

0

The h specifier in the printf format string says to expect a short int; however, you are casting the short ints to int, which is redundant and unnecessary since C promotes shorts to int by default.

Remove the h specifier and the casts.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
  • 1
    Default argument promotion in `printf` anyway converts `short` argument to `int`. – ouah Sep 16 '14 at 18:12
  • @ouah That occurred to me just minutes after I wrote my answer. You're absolutely right so I'm editing to fix. Thanks! – Carey Gregory Sep 16 '14 at 18:26
  • 0. According to Wikipedia, "h" expects `int` promoted from `short`. Without "h" it prints some numbers with 8 digits instead of 4. 1. Your suggestion does not fix the error. – beroal Sep 17 '14 at 21:50
  • Wikipedia is completely incorrect and Wikipedia is not where you should be going for programming information in the first place. Try an actual programming site such as cplusplus.com. I tested your code and reproduced the error. I then removed the casts and the `h` specifier and it worked. – Carey Gregory Sep 18 '14 at 01:51
  • 2
    @CareyGregory really not good to generalize like that, some programming concepts are explained quite well in wikipedia. – AndersK Sep 18 '14 at 06:56
  • @CareyGregory, checked again, does not work. What SML/NJ version do you use? – beroal Sep 18 '14 at 07:33
  • @Claptrap Some wiki articles are fine, sure, but with technical info one small error can have major detrimental effects, so why use a secondary source when primary sources are readily available? There are a number of sites that document standards such as `printf` format strings and all of them are superior to Wikipedia. – Carey Gregory Sep 18 '14 at 18:32
  • @beroal I am not using SML/NJ at all. It's not needed to reproduce your bug. Try taking SML/NJ out of the picture and I think you'll find your code still doesn't work. – Carey Gregory Sep 18 '14 at 18:33
  • @Carey Gregory: I clearly stated that invocation from C works as expected. – beroal Sep 19 '14 at 08:11
  • @beroal Not for me it doesn't. – Carey Gregory Sep 19 '14 at 13:23
0

My suspicion would be that there is no prototype in scope when you call the function, so the compiler performs default conversions on the arguments, which then confuses everything.

You should probably add to your GCC compiler options:

  • -Wmissing-prototypes
  • -Wstrict-prototypes
  • -Wold-style-definition
  • -Wold-style-declaration

Some older versions of GCC may not support the old-style arguments. It may be a salutary lesson when you first add these options. However, it very quickly becomes second nature to create code that conforms. Make sure you include the correct headers; you should never declare an extern function in a source file (you should include the header that contains the official extern declaration).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278