2

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?

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
Flabou
  • 115
  • 7
  • 2
    It's not possible in C because C has no way of creating new functions at run time. It would be straightforward in C++, though (especially with Boost). – Steve Summit Sep 04 '19 at 15:38
  • 1
    This is an example of a closure in Python. You can do something similar in C by storing the argument(s) in a structure and then passing the structure address to a wrapper function. That would get you down to one argument, but you can't eliminate the arguments completely. Doing so would require dynamic function creation (or at least argument binding), which C doesn't support. – Tom Karzes Sep 04 '19 at 15:40
  • `The argument ... will be implicitly used each time a call to the returned function is made`, and the returned function `is called without an argument`? How is the argument used if it's not used? – Brendan Sep 04 '19 at 15:45
  • @SteveSummit: I"m thinking the first function returns a structure containing a function pointer and the argument; so other code can call the function (via. the function pointer) and also do whatever is supposed to happen with the argument. – Brendan Sep 04 '19 at 15:50
  • @Brendan wouldn't the function call still need 1 argument, i.e. a pointer to the struct containing the "real" arguments? – Support Ukraine Sep 04 '19 at 15:54
  • @TomKarzes — what about the Foreign Function Interface library [`libffi`](https://github.com/libffi/libffi)? However, you still can't create functions at runtime in C. You can load shared objects (dynamic link libraries) and call functions from those — as long as you know the correct calling sequence — and you _could_ also run the compiler to create a shared object that's loaded dynamically, but that's pretty contorted. But `libffi` can help. It still isn't trivial. So, this isn't wholly disagreeing with you, Tom. If this feature is important to the OP, use a language that supports closures. – Jonathan Leffler Sep 04 '19 at 15:59
  • @SteveSummit C++ does not have that ability either. – Acorn Sep 04 '19 at 16:13
  • @Acorn Well, [functors](https://stackoverflow.com/questions/356950/what-are-c-functors-and-their-uses) come pretty close, and I think they'd let the OP do what he's trying to do. – Steve Summit Sep 04 '19 at 16:18
  • @SteveSummit Yeah, but that is not creating functions at runtime. The answer below from Eric is the same thing as a functor, in C. – Acorn Sep 04 '19 at 16:20
  • @JonathanLeffler I'm not familiar with libffi. Does it support dynamic argument binding? If so, I assume the user has to explicitly free the memory associated with the binding when done with it (or explicitly provide the memory to libffi when creating the binding). – Tom Karzes Sep 04 '19 at 16:21
  • I've not used `libffi` either, Tom, but I understand that it can be used to dynamic argument binding pretty thoroughly. Using its interface is portable; it's implementation is potentially different on each platform. – Jonathan Leffler Sep 04 '19 at 16:23

1 Answers1

5

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).
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • It is always worth noting that when you bodge up high-level language constructs in c like this you are simply exposing a possible way that the same features could be implemented "under the hood" of more expressive languages. They just do the bookkeeping for you. – dmckee --- ex-moderator kitten Sep 04 '19 at 16:27