I try to interface crystal to an existing C library for the first time.
Most things work out nicely but I have problem with passing NULL
and passing a parameter which will be assigned a value from the c function.
The example below is very reduced. The actual problem can be found in the real case below.
Prototype of c_fun to be used
/* prototype of c_func*/
int c_func(THATOBJ *thatobj, unsigned char *out, size_t *outlen)
Usage from C
.
THATOBJ *thatobj
size_t outlen;
unsigned char *out;
.
/* Determine buffer length */
c_func(thatobj, NULL, &outlen)
/* Allocate dyn memory */
out = malloc(outlen)
/* Process. by calling same c_func again! now with a result buffer */
c_func(thatobj, out, &outlen)
/* Now have result in out with size outlen */
/* Process given result and than release dyn memory*/
free(out)
.
If you are familiar with C some things strikes:
- NULL - is normally typedefed. Probably not defined in the imported library. How to define NULL in
Crystal
? - The
c_func
is used twice with different signature according to Crystals syntax.
You can’t have union on parameter definitions inCrystal
?. - The first call to
c_func
will assign value via a passed parameter
I have outlined the very crystal
code like with question marks ?? where I’m unsure.
Crystal source
.
?? Is `LibC` required
lib LibC
fun malloc(size : LibC::SizeT) : Void*
fun free(ptr : Void*) : Void
end
.
@[Link(ldflags: "thelib.a")]
lib LibTheLibC
.
alias THATOBJ = Char*
??alias OUTLEN = size_t outlen
??alias OUT = unsigned char *out
.
fun c_func_first_call = c_func(that : THATOBJ,
novalue : NULL??, len : ??OUTLEN)
fun c_func_second_call = c_func(that : THATOBJ,
hasvalue : OUT, len : ??OUTLEN)
.
end
.
# crytal usage
??OUTLEN outlen
??OUT out
.
LibTheLibC.c_func_first_call(THATOBJ, ??NULL, outlen)
out = LibC.malloc(outlen)
LibTheLibC.c_func_second_call(THATOBJ, out, outlen)
# Take care of the result out.
# release dyn memory
LibC.free(out)
.
Do I need two crystal functions to overcome the NULL | OUT parameter union type?
Looking forward to any advice.
Nice writings in
The crystal documentation
https://crystal-lang.org/reference/1.15/syntax_and_semantics/c_bindings/index.html
##Real case
https://docs.openssl.org/3.3/man3/EVP_PKEY_encrypt/#examples