Reputation: 20137
I'm aware that, because C isn't object oriented, the closest we can get to methods is using function pointers in a struct. This is just a thought exercise, but is it possible to have:
list.add(void* data)
without passing in the list itself as a parameter?
I know that:
list.add(list_t* list, void* data)
would be easy to implement, but is there any way, using whatever parts of C, to simulate a method in this way?
I recognize it's possible the answer is no, but please explain to me if you can! Thanks.
Upvotes: 4
Views: 3251
Reputation: 3375
If you want something simple, you can implement struct member functions using the blocks language extension. Blogged here.
You can use blocks to lambda-capture the associated struct, simulating the this pointer.
There's no virtual dispatch with this approach, so it's up to you whether you consider these true objects.
Upvotes: 0
Reputation: 13380
Not only instance methods, but you can even have CLOS-style generic methods with the right library. Laurent Deniau's COS library (also see paper: [link]) provides a full OO system you can just #include
and start using immediately; the method syntax is no heavier than any other function call.
It's apparently fast, too; the author claims to have gained a performance edge on similar code expressed in Objective-C (I'll take the claim itself with a pinch of salt, but even if they're comparable that's impressive).
Upvotes: 2
Reputation: 16406
To emulate OO method calls, you need objects with class or vtable pointers. If your list_t
contains, say, a funcs
member that points to a struct containing function pointers, one of which is add
, then your usage would be
list->funcs->add(list, data)
which you could capture in a variadic macro:
#define OO(obj, func, ...) (obj)->funcs->func(obj, __VA_ARGS__)
OO(list, add, data);
Upvotes: 1
Reputation: 72279
This is the prettiest syntax I got using variadic macros (C99):
#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))
struct class {
int a;
int (*method)(struct class* this, int b, int c);
};
int code(struct class* this, int b, int c) {
return this->a*b+c;
}
struct class constructor(int a) {
struct class result = {a, code};
return result;
}
#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))
#include <stdio.h>
int main() {
struct class obj = constructor(10);
int result = call(obj, method, 2, 3);
printf("%d\n", result);
return 0;
}
Upvotes: 6