cbindgen icon indicating copy to clipboard operation
cbindgen copied to clipboard

Better line breaking in function pointer types

Open fredszaq opened this issue 2 years ago • 1 comments

The current implementation never goes to a new line when writing a function pointer type, this can lead to long, difficult to read lines.

The goal of this change is to make that a bit more sensible.

Here is a rust code example

   1   │ pub type MyCallback = Option<unsafe extern "C" fn(a: usize, b: usize)>;
   2   │
   3   │ pub type MyOtherCallback =
   4   │     Option<unsafe extern "C" fn(a: usize, lot: usize, of: usize, args: usize)>;
   5   │
   6   │ #[no_mangle]
   7   │ pub extern "C" fn my_function(a: MyCallback, b: MyOtherCallback) {}

right now when generating the corresponding C header we get

   1   │ #include <stdarg.h>
   2   │ #include <stdbool.h>
   3   │ #include <stdint.h>
   4   │ #include <stdlib.h>
   5   │
   6   │ typedef void (*MyCallback)(uintptr_t a, uintptr_t b);
   7   │
   8   │ typedef void (*MyOtherCallback)(uintptr_t a, uintptr_t lot, uintptr_t of, uintptr_t args);
   9   │
  10   │ void my_function(MyCallback a, MyOtherCallback b);

line 8 here is already quite long and will be even longer if we add new args to MyOtherCallback

With the changes in this commit, we now get

   1   │ #include <stdarg.h>
   2   │ #include <stdbool.h>
   3   │ #include <stdint.h>
   4   │ #include <stdlib.h>
   5   │
   6   │ typedef void (*MyCallback)(uintptr_t a, uintptr_t b);
   7   │
   8   │ typedef void (*MyOtherCallback)(uintptr_t a,
   9   │                                 uintptr_t lot,
  10   │                                 uintptr_t of,
  11   │                                 uintptr_t args);
  12   │
  13   │ void my_function(MyCallback a, MyOtherCallback b);

which is way better and more scalable if new args are added to MyOtherCallback

The behavior is configurable using the already existing fn.args configuration parameter. In this case setting it to Horizontal gives back the same .h as previously and setting it to Vertical makes the generator go to a new line even for the shorter MyCallback declaration:

   1   │ #include <stdarg.h>
   2   │ #include <stdbool.h>
   3   │ #include <stdint.h>
   4   │ #include <stdlib.h>
   5   │
   6   │ typedef void (*MyCallback)(uintptr_t a,
   7   │                            uintptr_t b);
   8   │
   9   │ typedef void (*MyOtherCallback)(uintptr_t a,
  10   │                                 uintptr_t lot,
  11   │                                 uintptr_t of,
  12   │                                 uintptr_t args);
  13   │
  14   │ void my_function(MyCallback a,
  15   │                  MyOtherCallback b);

fredszaq avatar Oct 21 '22 14:10 fredszaq

Hey @emilio! Did you have time to take a look at this? I can do any change that you would deem necessary. Thanks a lot!

fredszaq avatar Nov 02 '22 13:11 fredszaq

Would be great to get a test for this, and it seems it needs formatting tho. Can you get to it? Otherwise I can try to do it when I find some time this week.

emilio avatar Nov 10 '22 12:11 emilio

added the test and formatted the code

fredszaq avatar Nov 10 '22 13:11 fredszaq

I got side-tracked with the "avoid extra work when measuring". Merged it in https://github.com/eqrion/cbindgen/commit/5fd38d541712928b7bf212da4f174f00acdceee9 :)

emilio avatar Nov 10 '22 13:11 emilio

great ! can we expect a version with it ?

fredszaq avatar Nov 10 '22 13:11 fredszaq