Greg
Greg

Reputation: 9168

C find which pointer called function

Scenario:

There are multiple C structs, each of which contains a function pointer to the same function. These pointers can be different if necessary (pointers to pointers, etc.), but must all point, eventually, to the same function.

Problem:

When the function is called from one of the pointers, I need to retrieve, within the function, which struct it was called from.

e.g.

typedef struct A {
    void * (*func)();
    ... /* Custom properties */
} * A;

typedef struct B {
    void * (*func)();
    ... /* Custom properties */
} * B;


A a_init() {
    A a;
    ... /* Custom initialisation, allocation, etc. */
    a->func = myFunc;
    return a;
}

B b_init() {
    B b;
    ... /* Custom initialisation, allocation, etc. */
    b->func = myFunc;
    return b;
}


int main () {
    A a = a_init();
    void *something = a->func();
}


void * myFunc () {
    // Need to get pointer to the instance of the struct this was called from here
}

Is there any way I can retrieve a pointer to the caller within myFunc? If necessary, I was thinking of creating pointers to pointers, etc. to the function, so each instance of an object would have a different pointer, and store all of them in a central location to match them up, but that obviously won't work if I can't even find the instance of the object or the pointer which was used. Any ideas?

Edit:

The question was intended a bit more broadly than I seem to have put it. Currying would be a great solution, if anyone has any ideas as to how to implement it in C. I had some ideas, but I just ended up coming right back to this spot with it.

Upvotes: 1

Views: 147

Answers (3)

Paul Richter
Paul Richter

Reputation: 6311

I don't think there is any way within the language to do that, without explicitly passing some identifier (as an argument or a global) to myFunc. The address of a_init() exists somwhere within the call stack, but it's not accessible from the program.

It's like if somebody showed up at your door unannounced, how would you find out where that person came from without asking?

Upvotes: 3

John Kugelman
John Kugelman

Reputation: 361547

Can't be done.

In C++ when you call member functions the compiler implicitly adds this as the first function argument. Mimicking obj->method() syntax in C won't work because there's no implicit this.

This doesn't mean that OO is impossible in C, simply that you can't use the same syntax as C++ or Java do to it. It can still be done, but you have to be explicit:

void * myFunc (void *this) {
    ...
}

a->func(a);
b->func(b);

Upvotes: 1

icktoofay
icktoofay

Reputation: 128993

You can't do that. What you may do, however, is define your structs like this:

typedef struct A {
    /* ... */
    void *(*func)(void *);
} A;

typedef struct B {
    /* ... */
    void *(*func)(void *);
} B;

And your function like this:

void *myFunc(void *the_struct) {
    /* ... */
}

And call like this:

A a = a_init();
void *something = a->func(a);

Alternatively, if you don't care about portability and for some reason need to be able to call it like a->func(), you may be able to create thunks/trampolines that add in the argument.

Upvotes: 1

Related Questions