Migwell
Migwell

Reputation: 20137

Is it possible to simulate object/instance methods in C?

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

Answers (4)

Chris Barrett
Chris Barrett

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

Alex Celeste
Alex Celeste

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

Jim Balter
Jim Balter

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

Kos
Kos

Reputation: 72279

This is the prettiest syntax I got using variadic macros (C99):

#define call(obj, method, ...) ((obj).method(&(obj), __VA_ARGS__))

usage (click for ideone):

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

Related Questions