Author Topic: A group of function pointers & a struct  (Read 8974 times)

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
A group of function pointers & a struct
« on: October 26, 2018, 12:47:23 AM »
About the only thing I really miss when writing C is when you really want a bunch of different plugins for the same code. It can be different types of loggers, or swapping the printing engine.

In C you typically do that by sending over a struct of function pointers + an opaque struct.

In OO we simply define an interface and implement it.

A simpler way, but one that doesn’t go all the way would be nice. Has this been discussed?

bas

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Re: A group of function pointers & a struct
« Reply #1 on: October 26, 2018, 09:14:48 AM »
I think I understand what you mean. Basically this is Interfaces.
C and C2 currently don't have those. The construct that comes closest is indeed a struct with function pointers.
The issue there is that it is easy to miss operators. So if a new interface function gets added, the derived implementations
will not complain. I've been thinking about this for a while, but so far have not found a nice solution.

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: A group of function pointers & a struct
« Reply #2 on: October 26, 2018, 11:23:09 AM »
Yeah, exactly. Ideally we'd write something like:

Code: [Select]
interface @Foo {
  func void do_something(Foo *foo, i32 an_argument);
  func void do_something_else(Foo *foo, i32 bar, i32 baz);
}

struct Test {
  i32 a;
  i32 b;
}

func void Test.do_something(Test *test, i32 foek) { .... };
func void Test.do_something_else(Test *test, i32 foek, i32 foek) { .... };

Test *test = malloc(sizeof(Test));
@Foo foo = @Foo(test);

func void try_something(@Foo foo) {
  foo.do_something(123);
  foo.do_something_else(2, 3);
}

Possibilities:

- "foo" is RC / ARCed or manually memory managed
- foo "owns" test and deallocates it or test is managed on its own or either is allowed.

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: A group of function pointers & a struct
« Reply #3 on: October 27, 2018, 01:10:47 AM »
Maybe we should start listing the options:

(1) Some sort of C++/Java style classes – possibly simplified so only struct + interface. Basically an opaque struct + pointer to a vtable. Very simple.

Advantages: fast, well known
Disadvantages: does not solve the generic issue. Grows like a cancer.

(2) ObjC style classes - message passing.

Advantages: no need for generics at all, classes used for large scale integration and doesn't replace normal structs, very simple runtime.
Disadvantages: Slow message passing, requires a rudimentary standard lib to be useful, often misunderstood and misapplied: people think it's supposed to be used like C++.

(3) The Go approach: tagged unions.

Advantages: Similar to (1), but does not invite class creation.
Disadvantages: Does not solve the generics issue, the "interface()" problem.

(4) Virtual wrapper (see above). Basically an explicit version of the Go approach, but less inviting to "program to interfaces"

(5) The manual C way

Advantages: Simple, clear
Disadvantages: Lots of manual labour, poor clarity

Please add more to the list!

Something else?

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: A group of function pointers & a struct
« Reply #4 on: October 27, 2018, 01:26:58 AM »
A quick addition. I think the challenge here is:

1. Prevent the feature from ballooning into a huge part of the language. Look at C++ on how things can grow from fairly simple beginnings. People want more, and it's often much easier to add a little something than to keep it lean. We see this over and over again. The joy of C is that it is still a very simple and lean language. There isn't much fat on it. Compare to other languages targetting the same space: those languages are really, really big and complex.

2. Do not amputate the feature beyond usefulness – people will want you to fix it and then you have problem (1) all over again.

3. Make it usable without providing libraries to go with it, it's an add-on for certain usecases – not a core feature.

4. Above all, keep the language lean.