1

I'm a bit confused as to how to implement the following. I want to have a function, func2, return a function that with call func1 with the specified parameters:

int func1(int x, int y, int z, int type){
    
    // Calculations
}

int ((*func2)(int x, int y, int z))(int type){

    // Return a pointer to func1 that with get x, y, z as parameters 
    // when called later, with type = type being fixed
}

Use:

my_func = func2(3);
printf("result = %d\n", my_func(1,2,3));
Ccret
  • 11
  • 1
  • Does this answer your question? [Is there a a way to achieve closures in C](https://stackoverflow.com/questions/4393716/is-there-a-a-way-to-achieve-closures-in-c) – Tom Karzes Oct 31 '20 at 14:58
  • There are lots of existing answers to this question. See the duplicate link. Some use FFCALL, and some are just straight C. – Tom Karzes Oct 31 '20 at 15:01
  • Hm, it looks like GNU has a [callback library](https://www.gnu.org/software/libffcall/callback.html) as well. The advantage to these solutions is that they give you a callable function that has its own associated state. Unfortunately, there's no way to implement this directly in C. – Tom Karzes Oct 31 '20 at 15:22

3 Answers3

1

For this to work you need something called a closure which is basically a record with the function and the type as fields. Below is an example to illustrate the idea. In a real program you also need to check that malloc doesn't return NULL, and free the memory.

#include <stdio.h>
#include <stdlib.h>

typedef struct ClosureDesc *Closure;

struct ClosureDesc {
    int type;
    int (*function)(Closure c, int x, int y, int z);
};


int func1(Closure c, int x, int y, int z)
{
    return c->type;
}


Closure func2(int type)
{
    Closure c;

    c = malloc(sizeof *c);
    c->type = type;
    c->function = func1;
    return c;
}


int main(void)
{
    Closure my_func;

    my_func = func2(3);
    printf("result = %d\n", my_func->function(my_func, 1,2,3));
    return 0;
}
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60
  • You left out the all-important step of *freeing* the closure when done with it. It would probably also be better not to bury the pointer in a `typedef`, but instead expose it so people are aware of it (which probably would have prevented the memory leak bug). – Tom Karzes Oct 31 '20 at 14:49
  • @TomKarzes Indeed but in this short example it will be freed when the program exits. Updated the answer to highlight this. – August Karlstrom Oct 31 '20 at 14:50
  • That's a bad way to look at it. OP will need to know how to use this in more than just a "wait until exit to free everything" context. And it has the bad practice of hiding the pointer in a `typedef`, which makes it that much more likely that it will have bugs like this. – Tom Karzes Oct 31 '20 at 14:52
  • but it does not select the correct function depending on the type. So where is the solution? – 0___________ Oct 31 '20 at 14:58
  • @P__JsupportswomeninPoland It all depends on how you interpret the question. – August Karlstrom Oct 31 '20 at 15:02
  • @AugustKarlstrom he wants function returning a pointer to function depending on the parameter. IMO it is quite clear – 0___________ Oct 31 '20 at 15:03
  • Thank you for trying to provide me with a solution! Though, I'd prefer it if there was a way to call a function immediately wihtout accessing the member of a structure. type, participates in the calculations performed and can take a wide range of numbers - so it can't be used as a function selector. – Ccret Oct 31 '20 at 15:40
  • @Ccret Unfortunately, C unlike e.g. Javascript does not support this. – August Karlstrom Oct 31 '20 at 15:47
  • @AugustKarlstrom Thank you, unfortunately there seems to be no workaround. – Ccret Oct 31 '20 at 15:52
  • @Ccret If you explain the underlying problem (in a different question) there may be another solution. See also https://en.wikipedia.org/wiki/XY_problem – August Karlstrom Oct 31 '20 at 16:00
0

Function pointers syntax is a bit confusing but you can make it easier typedefing the functions itself. Then you can use "normal" pointer syntax.

typedef int func(int,int,int);

int func1(int x, int y, int z){
    // Calculations
    return 1;
}

int func2(int x, int y, int z){
    // Calculations
    return 2;
}

int func3(int x, int y, int z){
    // Calculations
    return 3;
}


func *selectfunc(int type)
{
    func *f = NULL;
    switch(type)
    {
        case 1:
            f = func1;
            break;
        case 2:
            f = func2;
            break;
        case 3:
            f = func3;
            break;
    }
    return f;
}


int main(void)
{
    int type = rand()%3;
    printf("%d", selectfunc(type)(1,2,3));
}

or

    func *fptr = selectfunc(2);
    fptr(1,2,3);
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Thank you for trying to provide me with a solution, close to the format I had in mind! Though, `type` can get a wide range of values and can't be used as a function selector. – Ccret Oct 31 '20 at 15:36
  • it is only an example – 0___________ Oct 31 '20 at 15:42
  • It doesn't pass `type` to func1. I'd like `type` to get a value once and then this value to be used to perform calculations when calling `fptr(1,2,3)`. – Ccret Oct 31 '20 at 15:50
  • so modify your question. Do you think that I read telepatically from your mind. In your example function pointer passes also **3** parameters – 0___________ Oct 31 '20 at 16:38
  • I think it's clear in the declaration of `func1` that it needs 4 parameters. – Ccret Oct 31 '20 at 18:07
  • `func1(int x, int y, int z, int type)` – Ccret Oct 31 '20 at 18:34
0

Here’s what I think you’re going for:

int func1( int x, int y, int z )
{
  ...
}

/**
 * func2 takes an integer parameter and returns a
 * pointer to a function that takes 3 integer
 * parameters and returns int
 */
int (*func2(int type))(int, int, int)
{
  /**
   * This example is based on what you wrote in your 
   * question.  Regardless of how you actually select
   * which function to return based on the input, the
   * return statement will be the same.
   */
  switch ( type )
  {
    case 3:
      return func1;
      break;

    default:
      break;
  }
  return NULL;
}

int main( void )
{
  int (*my_func)(int, int, int);
  ...
  my_func = func2( 3 );
  if ( my_func )
    printf( "result = %d\n", my_func( 1, 2, 3 ) );
  ...
}

If you write func2 such that it can never return NULL and you want your co-workers to throw things at you, you can dispense with the my_func variable and just write

printf( "result = %d\n", func2(3)(1, 2, 3));

I wouldn’t recommend it though, unless you like rude comments in code reviews.

John Bode
  • 119,563
  • 19
  • 122
  • 198