The Crystal Programming Language Forum

C Bindings with more than 8 parameters

I have a weird issue when I have a function defined in a C library which use more than 8 parameters

fun testme(tc : UInt32, c : UInt32, p : UInt32,  pw : UInt8*, pl : UInt32, s : UInt8*, sl : UInt32, h : UInt8*) : Int32
# If I call :
s = Array(UInt8).new()
s<<53<<2<<2;
Mylib.testme(1,1, 1, s, 3, s, 3, s)

The library gets a random value for the sl argument

But if I remove the first or the last argument from the function signature then I have the correct value for sl (which is 3 in my example). I wonder what could be wrong?

Hi!

Could you show the C file/headers? Also it’s always better to include a complete example that one can copy, paste and run.

Hello,
Thank you for your quick answer, the C header is:

PUBLIC int testme2(/*const uint32_t c,*/ const uint32_t c,
                                   const uint32_t p, const void *pwd,
                                   const size_t pwdlen, const void *s,
                                   const size_t sl, void *hash/*,
                                   const size_t hashlen*/);
PUBLIC int testme3(const uint32_t c, const uint32_t c,
                                   const uint32_t p, const void *pwd,
                                   const size_t pwdlen, const void *s,
                                   const size_t sl, void *hash/*,
                                   const size_t hashlen*/);

testme2 is working but not testme3. I noticed that if I do this in testme3:

	printf("bad sl is:%u\n",saltlen);
	printf("signed sl is:%d\n",saltlen);

Then ‘bad slen’ prints a big number that seems random, e.g: 140213502345219, 140389596004355
(it is never the same), while ‘signed slen’ output the correct value (3).
But both size_t on the C side or UInt32 on the Crystal side are unsigned?

Umm you know that size_t is not UInt32, right?
Try SizeT

Also you have a void* as 4th parameter in your C example, but not in your original Crystal example, there you seem to type these as UInt8*. Use Void*.

With SizeT I have the following:
Error: undefined constant SizeT
(my Crystal version is 0.31.1)

The UInt8* seems to work, I would imagine Crystal can cast pointers to Void*?

Yes, you can cast any Pointer(T) to any other. SizeT is defined within LibC, so it’s LibC::SizeT.

Yes it works, thank you very much for your support!