On Mon, Apr 19, 2021 at 3:17 AM Kent Gibson <warthog618@xxxxxxxxx> wrote: > [snip -> long discussion on the libgpiod C API] Hi Kent, I was working on the next iteration of the code and I'm struggling with the implementation of some elements without the concept of attributes. So I initially liked the idea of variadic functions but they won't work for language bindings so that's a no go. On that note: I wanted to get some inspiration from your go library but your elegant API makes use of go features (like interfaces) we don't have in C. The problem we have is basically about implementing primary and secondary line configuration objects - where the primary contains the default config for all requested lines and the secondary can override certain config options (should zeroed values for enumerated types mean - don't override?) for certain lines. The basic line config structure (let's call it struct gpiod_line_config) can be very simple and have the following mutators: struct gpiod_line_config *cfg = gpiod_line_config_new(); gpiod_line_config_set_direction(cfg, GPIOD_LINE_CONFIG_DIRECTION_OUTPUT); gpiod_line_config_set_active_low(cfg, true); and so on for for drive, bias, edge, debounce, realtime clock. Output values would be set like this: unsigned int values[] = { 0, 1, 1, 0 }, num_lines = 4; gpiod_line_config_set_output_values(cfg, num_lines, values); One can imagine a simple request with the same config for all lines as: gpiod_chip_request_lines(chip, req_cfg, line_cfg); Where req_cfg configures request-specific options, and line_cfg contains the above line config. I'm still not convinced that gpiod_request_options is the better name, I think I prefer the juxtaposition of the two names: line_config and request_config. Now how do we pass a composite line config with overridden values in C without interfaces etc.? One idea I have is to add a new object called struct gpiod_line_config_ext (for extended) that would take one primary config and an arbitrary number of secondary configs with the following example use-case: struct gpiod_line_config_ext *ext_cfg = gpiod_line_config_ext_new(); unsigned int offsets[] = { 2, 3 }; /* Add the default config for this request. */ gpiod_line_config_ext_set_primary_config(ext_cfg, line_cfg); /* Add a secondary config for 2 lines with offsets: 2 and 3. */ gpiod_line_config_ext_add_secondary_config(ext_cfg, other_line_cfg, 2, offsets); gpiod_chip_request_lines_ext(chip, req_cfg, ext_cfg); Does this make sense? I'm worried about the resource management here. Who should be responsible for freeing the config structures? Should the extended config take ownership? Should the user remain responsible? Back to reference counting for these objects? Is this even a good idea? Please let me know what you think, I could use some advice. Best Regards, Bartosz