ralux ralux - 1 month ago 6
C Question

assign member C function pointer with another member as default argument

Let's say I have a C struct

struct MULTIPLY{
int by; //some factor to multiply, can be seen as instance id/key
int (*get)(int c); //the function that actually returns the result
} multiply;


and that I want to assign the multiply instance using the following function

int product(int a, int b)
{
return a*b;
}


In main I would like to assign to multiply->get a function that computes the product of multiply->by and a new argument. I could do this by passing a pointer to the multiply instance, but I wonder if there is any way to call it without changing the signature of get function

multiply->by = 2;
multiply->get(int c) = product(multiply->by, c); ???

multiply->get(5); // 10


Thanks!

EDIT:

Thanks for the answers. Indeed, by default there's no way to do closures in C. I was looking for a workaround. I found 2 solutions but are quite limited. One is Blocks.h (also works with obj-C) needs to be compiled with Clang. The other is FFCALL (http://www.haible.de/bruno/packages-ffcall-README.html ), which is limited to some processor architectures.

So, in my case, I decided to just pass some pointers around to access the id (by, in this example). Pretty much what Tomasz Lewowski suggested.

Answer

Generally C does not support partial function application, and you need all signatures and names set up in compilation time, and functions generally cannot be defined in runtime (kernel can load them, but let's ignore it - userspace apps don't do it). However...

On some level of abstraction this is possible (e.g. many interpreters written in C allow that), but for pure C it's not directly possible and, if you need to do it, you probably picked up a wrong language.

You can work around it by using an emulation of object-oriented approach (always passing another argument as this pointer). Pseudocode:

struct MULTIPLY{
   int by;            //some factor to multiply, can be seen as instance id/key

   // intended private
   int (*f)(int, int);
} multiply;

int call(MULTIPLY m, int i) {
  return *(m.f)(by, i);
}

MULTIPLY m = {2, product} // + allocation etc.;
call(m, 5); // actual call

It's much nicer in languages which really support object-oriented design, but you can do it in C as well - still, you need to remember about this additional argument (this, context, self or however you want to call it), which kinda messes up the code.

If you're ultra-determined to do it without any additional arguments, you can make a global MULTIPLY instance and use it from call. This would be something like:

// global scope!
MULTIPLY m;
int call(int i) {
    return *(m.f)(m.by, i);
}

// m initialization etc.
// some stuff happening
call(5);

But please, don't. It'll be ultra-hard to maintain, because of the global binding. Plus, it won't work exactly as a closure - once you change value in m, all places where you've passed call will start to behave differently (previous, object oriented approach will work properly everywhere).