C найти, какой указатель вызвал функцию - PullRequest
1 голос
/ 11 февраля 2012

Сценарий:

Существует несколько структур C, каждая из которых содержит указатель на одну и ту же функцию.Эти указатели могут быть разными, если это необходимо (указатели на указатели и т. Д.), Но в конечном итоге все они должны указывать на одну и ту же функцию.

Проблема:

Когда функция вызывается из одного изуказатели, которые мне нужно получить, внутри функции, из структуры которой она была вызвана.

например,

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
}

Есть ли способ получить указатель на вызывающего в myFunc?При необходимости я думал о создании указателей на указатели и т. Д. На функцию, чтобы у каждого экземпляра объекта был свой указатель, и все они сохранялись бы в центральном месте, чтобы соответствовать им, но это явно не будетработать, если я не могу даже найти экземпляр объекта или указатель, который был использован.Есть идеи?

Редактировать:

Вопрос был задан несколько шире, чем я, по-видимому, сформулировал.Карри было бы отличным решением, если у кого-то есть какие-либо идеи относительно того, как реализовать его в C. У меня были некоторые идеи, но я просто вернулся к этому месту вместе с ним.

Ответы [ 3 ]

3 голосов
/ 11 февраля 2012

Я не думаю, что в языке есть способ сделать это без явной передачи некоторого идентификатора (в качестве аргумента или глобального) в myFunc.Адрес a_init() существует где-то в стеке вызовов, но он недоступен из программы.

Это как если бы кто-то появился у вашей двери без предупреждения, как бы вы узнали, откуда этот человек пришел, не спросив?

1 голос
/ 11 февраля 2012

Не может быть сделано.

В C ++, когда вы вызываете функции-члены, компилятор неявно добавляет this в качестве первого аргумента функции.Подражание синтаксису obj->method() в C не будет работать, потому что нет неявного this.

Это не означает, что OO невозможно в C, просто вы не можете использовать тот же синтаксис, что и в C ++ илиЯва сделаю к этому.Это еще можно сделать, но вы должны быть явными:

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

a->func(a);
b->func(b);
1 голос
/ 11 февраля 2012

Вы не можете этого сделать. Однако, что вы можете сделать, так это определить ваши struct s:

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

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

И ваша функция такова:

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

И звоните вот так:

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

В качестве альтернативы, если вас не волнует переносимость, и по какой-то причине вам нужно иметь возможность вызывать его как a->func(), вы можете создавать блоки / трамплины, которые добавляют в аргумент.

...