News for hackers. Stuff that matters.
Re:Plain C API design, the real world Kobayashi Maru test by mintplant on Sunday April 16, 2023 @02:51PM (#35593108)
Composition?

    typedef struct { /* ... */ } context;
    typedef struct {
      context ctx;
      /* ... */
    } foo_context;
    typedef struct {
      context ctx;
      /* ... */
    } bar_context;

    void some_general_method(context* ctx, int a, int b);
    void some_foo_specific_method(foo_context* foo_ctx, int c, int d);

    foo_context* foo_ctx;
    some_foo_specific_method(foo_ctx, 0, 0);
    some_general_method(&foo_ctx->ctx, 1, 1);
For checked downcasts, you could include an enum type tag inside `context` and have something like `foo_context* as_foo_context(context* ctx)` for downcasts, which, if `context` is at the beginning of `foo_context`, could just check the tag and cast the `ctx` pointer to `foo_context*` (or do a little pointer arithmetic if `context` is somewhere else in the containing struct). Return `NULL` (or assert) if the tag doesn't match.
Re:Plain C API design, the real world Kobayashi Maru test by dromtrund on Sunday April 16, 2023 @04:16PM (#35593877)
+1, this approach will also highlight cases where you're trying to generalize something that isn't as generic as you thought.

I'd argue that the need for downcasting in a method working on the inner context would also be a code smell, and that you might want to reconsider the context split. In some cases, there's no way around it (like async events), but it might be more appropriate to pass additional context or a callback instead, to avoid a circular dependency.

Re:Plain C API design, the real world Kobayashi Maru test by uecker on Sunday April 16, 2023 @05:12PM (#35594317)
I use this technique a lot and it is very powerful.
Re:Plain C API design, the real world Kobayashi Maru test by zcbenz on Sunday April 16, 2023 @11:06PM (#35596456)
Adding fields to context will break ABI compatibility.

To work around the problem, some libraries add padding fields, and some require passing the size of struct to determine ABI version.

Re:Plain C API design, the real world Kobayashi Maru test by cozzyd on Monday April 17, 2023 @11:25PM (#35609613)
I'm guessing context here is a pointer or a handle?
Re:Plain C API design, the real world Kobayashi Maru test by icedchai on Monday April 17, 2023 @05:36PM (#35606936)
I first saw this technique used in the late 80's, with the Amiga operating system. Most of the APIs were built on this sort of pattern.