Указатель на функцию, которая принимает указатель на другую функцию в качестве аргумента

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

Все, что я хочу сделать, это, имея указатель на функцию, обернуть его внутри другой функции, которая принимает указатель на функцию в качестве аргумента, и сделать указатель на более позднюю. Лучше в коде:

void do_nothing_1() {}
void do_nothing_2() {}

void wrapper(void(*f)()) { f(); }

int main() {

    // the following will call the function
    // but i just want a pointer of whats being called
    funcion_pointer_1 = wrapper(do_nothing_1);
    funcion_pointer_2 = wrapper(do_nothing_2);

    return 0;
}

Я заранее извиняюсь, если вопрос не имеет никакого смысла, пожалуйста, помогите мне прояснить его, а не просто понизить его.

Изменить: учитывая очевидную сложность получения желаемых результатов из-за неясности требований, я буду немного более конкретным в отношении того, что я ищу.

Внутри структуры у меня есть указатель на функцию:

struct my_struct {
    int (* run)(void);
}

Что я хочу сделать, так это изменить эту функцию, и поэтому я использую оболочку. Так, например, если foo возвращает void, измените это на int. Кроме того, запустите некоторый код перед выполнением foo:

int wrapper(void (*foo)()) {

    // exec some stuff here

    foo();

    return 0;
}

В конечном счете, я хочу, чтобы при выполнении функции, соответствующей указателю *run из моей структуры, выполнить некоторые действия перед выполнением run() и изменить тип возвращаемого значения.


person Oscar Wahltinez    schedule 09.06.2012    source источник
comment
Вам нужен указатель функции на wrapper?   -  person K-ballo    schedule 09.06.2012
comment
точнее обертка(foo)   -  person Oscar Wahltinez    schedule 09.06.2012
comment
Можете ли вы изменить свой код, чтобы было не так много foo - затенение усложнит ситуацию.   -  person jedwards    schedule 09.06.2012
comment
wrapper(foo) не является функцией, поэтому вы не можете получить указатель функции на нее.   -  person K-ballo    schedule 09.06.2012
comment
Вы ищете замыкания? Если это так, рассмотрите что-то вроде libffcall.   -  person Adam Rosenfield    schedule 09.06.2012
comment
тогда это просто вызывающая функция? мне нужно реализовать структуру для достижения того, что я ищу, или это просто невозможно?   -  person Oscar Wahltinez    schedule 09.06.2012
comment
Указатель функции не содержит информации о параметрах функции, если это то, что вы пытаетесь сделать. Это просто адрес функции.   -  person tomlogic    schedule 09.06.2012


Ответы (1)


При борьбе с правильным синтаксисом полезно использовать typedefs, чтобы прояснить ситуацию. Не только для себя, когда вы пишете код, но и для всех, кому нужно его поддерживать или просто пытаться понять, что он делает.

Вам нужен указатель на функцию, которая принимает указатель на другую функцию в качестве аргумента. Начните с аргумента, функции без параметров и без возвращаемого значения:

typedef void (*void_handler_t)( void);

А теперь указатель на функцию-оболочку, который принимает параметр указателя на функцию и не имеет возвращаемого значения:

typedef void (*wrapper_handler_t)( void_handler void_fn);

И код:

void foo( void) {}
void wrapper( void_handler_t wrapped_fn)
{
    wrapped_fn();
}

int main( int argc, char *argv[])
{
    wrapper_handler_t function_pointer;

    function_pointer = &wrapper;
    function_pointer( &foo);

    return 0;
}
person tomlogic    schedule 09.06.2012
comment
Отличный совет о синтаксисе и typedef, я проголосую только за это, спасибо. Я не уверен, делает ли это то, что я ищу. Есть ли способ сделать что-то вроде: function_pointer = &wrapper(&foo); указатель_функции(); - person Oscar Wahltinez; 09.06.2012
comment
typedefs для всего, кроме непрозрачных данных, ведут только к убийству - person tbert; 09.06.2012
comment
@tbert что ты имеешь против typedef? Считается ли это плохой практикой? - person Oscar Wahltinez; 09.06.2012
comment
@omtinez приходится деконструировать код, в котором все структуры вызываются foo_t, что приводит к невозможности использования структур данных за пределами одного файла без необходимости содомизировать ваши схемы именования и т. д .; в основном, потеря ясности, которая приходит вместе с их постоянным чрезмерным использованием - person tbert; 09.06.2012
comment
@tbert: я не уверен, что понимаю, почему struct foo понятнее, чем foo_t. Мне не нравятся люди, которые typedef указывают на другие типы, но я думаю, что это имеет большой смысл для указателей на функции, особенно когда у вас есть эти указатели в качестве элементов в других структурах или параметров других функций. - person tomlogic; 09.06.2012
comment
@tomlogic чем foo_t понятнее, чем struct foo? Я знаю, что я могу сделать со структурой, потому что я знаю, что это такое и что в нее нужно втыкать; Я вижу foo_t и не знаю, является ли это структурой, целым числом, символом или каким-то странным новым типом данных, к которому мир до сих пор не был причастен. На мой взгляд (и, честно говоря, я собираюсь пойти на все, если вы сделаете это неправильно), наличие типа данных foo_t указывает на то, что внутри нет частей, обслуживаемых пользователем. - person tbert; 09.06.2012