Flabou
Flabou

Reputation: 115

How to create a function that returns another function, encompassing a given argument implicitly in C?

I want to have a function that returns a function that is called without an argument, even though the original function must be called with an argument. The argument is passed to the first function and will be implicitly used each time a call to the returned function is made.

I am aware of function pointers in C but I don't know if they can be used in such a way. I know how to do this in python as shown in the following sample code :

def foo(some_argument):
    print(some_argument)

def register_callback(function, argument):
    def new_function():
        function(argument)

    return new_function

bar = register_callback(foo,"bar")

bar()

From what I read, this way is not possible in C because we can't nest function definitions. Is this possible and if so what would be the proper way to do it?

Upvotes: 2

Views: 105

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 223264

About all you can do in C is create a record (a struct) containing both the function pointer and the argument to pass and then use that record as the “thing” that is called, with the assistance of a wrapper function that does the actual calling.

#include <stdio.h>


typedef int SomeType;   //  Sample type for demonstration.


//  Define a record to hold a function pointer and the argument we want to pass.
typedef struct
{
    void (*Function)(SomeType); //  Function to call.
    SomeType Argument;  //  Argument to pass.
} Closure;


//  Define some sample functions.
static void A(SomeType x) { printf("Called %s(%d).\n", __func__, x); }
static void B(SomeType x) { printf("Called %s(%d).\n", __func__, x); }


//  Define a function that returns a closure.
static Closure foo(int Which, SomeType x)
{
    return (Closure) { .Function = Which & 1 ? B : A, .Argument = x };
}


//  Define a function to call a closure.
static void Call(Closure C) { C.Function(C.Argument); }


int main(void)
{
    Closure a = foo(0, 34);
    Closure b = foo(1, 79);
    Call(a);
    Call(b);
}

Output:

Called A(34).
Called B(79).

Upvotes: 5

Related Questions