Find a proper solution for variadic methods when available.
In rust you can't define variadic methods, at least as of right now.
If that changes, we would be able to generate the convenience methods we use for the rest of methods. See https://github.com/servo/rust-bindgen/issues/402#issuecomment-273426241.
cc @kkimdev
As of today, Rust does not support variadic functions unless they are extern, free ones. I've been thinking about different ways to solve this, each one of them with their advantages and disadvantages, let's say we have an extern function like this:
extern "C" {
fn foo_bar(foo: &Foo, a: A, ...);
}
Then we could either:
Use macros
One option would be to add a variadic_call macro to the generated bindings:
variadic_call!(foo.bar(a, v0, v1, v2)) // desugars to bar(&foo, v0, v1, v2)
This isn't great as we wouldn't be able to do all the deref tricks such as handling &mut foo &foo and so on. As usual, macros would also make the code less readable and we wouldn't win anything tbh.
Use tuples
This would be way more convoluted but it would allow the users to do
foo.bar(a, (10,));
foo.bar(a, (10, b"hello"));
foo.bar(a, (10, b"hello", false));
The exposed method would look like this
impl Foo {
/// Call `bar` with variadic arguments using tuples.
///
/// A call with no variadic arguments would use `()` as: `foo.bar(a, ())`.
unsafe fn bar(&self, a: A, varargs: impl VarArgs) {
varargs.call_foo_bar(self, a)
}
}
Then the definition and implementations of VarArgs would be
trait VarArgs {
/// There should be one method in this trait for each variadic method.
#[doc(hidden)]
unsafe fn call_foo_bar(self, foo: &Foo, a: A);
}
// This would be either macro generated or generated by bindgen up to a certain tuple length.
impl VarArgs for () {
unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
foo_bar(foo, a)
}
}
impl<T1> VarArgs for (T1,) {
unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
foo_bar(foo, a, self.0)
}
}
impl<T1, T2> VarArgs for (T1, T2) {
unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
foo_bar(foo, a, self.0, self.1)
}
}
The disadvantage here is having to expose this VarArgs trait but I think with some good documentation it would work nicely.
Let me know what you think :)