So I need to create a function wrapping a variadic c function (https://jcupitt.github.io/libvips/API/current/libvips-resample.html#vips-thumbnail) in rust.
This function takes some arguments and lastly a "NULL-terminated list of optional named arguments".
c function:
int vips_thumbnail (const char *filename, VipsImage **out, int width, ...);
example calling it from rust with a optional height parameter:
vips_thumbnail(some_path.as_ptr(), &mut out_ptr, width as i32, "height\0".as_ptr(), height as i32, null() as *const c_char);
Simple enough.
But as I'd like to make a wrapping function I'd like to have those optional options in a struct like:
pub struct VipsThumbnailOptions {
pub height: Option<i32>,
pub size: Option<VipsSize>,
pub auto_rotate: Option<bool>,
pub crop: Option<VipsInteresting>,
pub linear: Option<bool>,
pub import_profile: Option<String>,
pub export_profile: Option<String>,
pub intent: Option<VipsIntent>,
}
and then in my wrapping function only pass the options that aren't None.
First thought:
if options.height.is_none() && options.size.is_none() && options.auto_rotate.is_none() && options.crop.is_none() && options.linear.is_none() && options.import_profile.is_none() && options.export_profile.is_none() && options.intent.is_none() {
vips_thumbnail(some_path.as_ptr(), &mut out_ptr, null() as *const c_char);
}
if options.height.is_some() && options.size.is_none() && options.auto_rotate.is_none() && options.crop.is_none() && options.linear.is_none() && options.import_profile.is_none() && options.export_profile.is_none() && options.intent.is_none() {
vips_thumbnail(some_path.as_ptr(), &mut out_ptr, width as i32, "height\0".as_ptr(), options.height.unwrap() as i32, null() as *const c_char);
}
...
That would be the most naive way I think, I guess one could check for one option at the time and build a big tree of if else and make less checks but I'd say it wouldn't be fun to write either way, with those 8 options it would be 255 combinations and I believe there are other functions that take more, say 16 would mean 2^16=65536 combinations. So, my first question, is it possible write a macro to generate those if statements and function calls with something like call_vips_thumbnail_with_variadic_args!(some_path, out_ptr, width, height, size, auto_rotate, crop, linear, import_profile, export_profile, intent);
I think that even if it's possible to generate it and something I would like to some extent this might not be a sustainable solution, it is quite a few if statements event if generated.
So if this isn't possible what's next?
Well I found this (https://bsteinb.github.io/rsmpi/libffi/low/fn.prep_cif_var.html), seems that could be used to do the work and the closest example would be in the test suite of libffi (https://github.com/libffi/libffi/blob/65da63abc843fe448aaa86015d094cf016f325ba/testsuite/libffi.call/va_1.c) but doing it in rust is something I stuggle with.
Also, is using libffi good?, performat? etc.
But perhaps mixing those methods? Like do the macro for the most used options say up to 6-8 and then if there's no match on those do the libffi way.
So my second question, is there any examples of using prep_cif_var in rust? If not, is there anyone who might want to help me create an example of doing just that?
Oh then there's the question of "have I missed something simpler, better or whatever"?