rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Emulate variadic methods using tuples

Open pvdrz opened this issue 3 years ago • 0 comments

This PR introduces a new flag --tuple-varargs-len=<LEN> which can be used to emulate variadic methods using tuples of length up to <LEN>.

Example

If the generated function signature for a variadic method is:

extern "C" {
    fn foo_bar(foo: &Foo, a: A, ...);
}

and the --tuple-varargs-len flag is set. A new method for the type Foo is introduced:

impl Foo {
    unsafe fn bar(&self, a: A, varargs: impl VarArgs) {
        varargs.call_foo_bar(self, a)
    }
}

The user would use such method like this:

foo.bar(a, ()); // 0 variadic args
foo.bar(a, (10,)); // 1 variadic arg
foo.bar(a, (10, b"hello")); // 2 variadic args
foo.bar(a, (10, b"hello", false)); // 3 variadic args
...

To do this, the VarArgs trait is declared and implemented automatically up to the value of --tuple-varargs-len:

trait VarArgs {
    unsafe fn call_foo_bar(self, foo: &Foo, a: A);
}

impl VarArgs for () {
    unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
        let () = self;
        foo_bar(foo, a)
    }
}

impl<T0> VarArgs for (T0,) {
    unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
        let (t0, ) = self;
        foo_bar(foo, a, t0)
    }
}

impl<T0, T1> VarArgs for (T0, T1) {
    unsafe fn call_foo_bar(self, foo: &Foo, a: A) {
        let (t0, t1) = self;
        foo_bar(foo, a, t0, t1)
    }
}

This has some disadvantages, such as the user not being able to just do foo.bar(a) or foo,bar(a, v) without getting somewhat confusing errors but this could be mitigated by properly documenting the VarArgs trait.

Fixes #407

pvdrz avatar Sep 20 '22 20:09 pvdrz