Pass Lines of Code as an Argument in C - c

I'm working on a project in which I'm on a fairly strict word limit (I'm not 100% certain what qualifies as a word).
I'm looking to pass lines of code into a function as an argument, I've seen this done in JavaScript but I cannot find anything on it in C.
This is about what I'm looking for:
void onTime(int a, Code myCode) {
if(timer == a) {
//run myCode
}
}
And I could use it something like this:
onTime(45, {
//code
});
Is there a way in C that I can do something like this?

C doesn't allow inline code (referred to as lambda expressions in other languages) to be passed around. What you can do however is pass a pointer to an existing function.
// typedef for a function that takes no arguments and returns void
typedef void (*ftype)(void);
void func_to_run(void)
{
...
}
void onTime(int a, ftype code) {
if(timer == a) {
code();
}
}
You could then call it like this:
ontime(45, func_to_run);
If you want the function to be packaged with a set of values that it uses, similarly to C++ classes which have member functions which can access member variables, that involves some trickery.
Here's an example of how you might do something like this:
#include <stdio.h>
typedef int (*ftype)(int, int);
struct c {
int a;
int b;
ftype add_func;
ftype sub_func;
};
#define ADD(s) (s)->add_func((s)->a,(s)->b)
#define SUB(s) (s)->sub_func((s)->a,(s)->b)
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
void run(struct c *op)
{
printf("add result=%d\n", ADD(op));
printf("sub result=%d\n", SUB(op));
}
int main()
{
struct c c1 = { 1, 2, add, sub };
struct c c2 = { 3, 4, add, sub };
struct c c3 = { 6, 1, add, sub };
struct c c4 = { 9, 4, add, sub };
run(&c1);
run(&c2);
run(&c3);
run(&c4);
}
Here we define a struct c which contains function pointers for two functions and two other variables.
The macros ADD and SUB are used to run the "member" functions of the struct and pass them the "private" members to use. It hides the fact that the actual function being called is independent of the parameters being passed to it.
This code outputs:
add result=3
sub result=-1
add result=7
sub result=-1
add result=7
sub result=5
add result=13
sub result=5
Of course, once you start doing this you're (crudely) doing what C++ is doing and would probably be better off switching to C++ which is made for OOP and now supports lambdas.

Related

using function names as functions in a C macro

Suppose i have code like this in my program:
if (!strcmp(current, "sin")) {
pushFloat(sin(x), &operands);
} else if (!strcmp(current, "cos")) {
pushFloat(cos(x), &operands);
} else if (!strcmp(current, "tan")) {
pushFloat(tan(x), &operands);
} else if (!strcmp(current, "ctg")) {
pushFloat(1. / tan(x), &operands);
} else if (!strcmp(current, "ln")) {
pushFloat(log(x), &operands);
} else if (!strcmp(current, "sqrt")) {
pushFloat(sqrt(x), &operands);
}
There are function names such as "sin" or "cos" saved in the current char array
Instead of using this long if block, or replacing it with an even longer switch block, i wanted to write a simple macro like this: #define PUSHFUNC(stack, func, value)(pushFloat(func(value), &stack)) and call it like this PUSHFUNC(operands, current, x)
Doing it this way creates an error "current is not a function or function pointer". I initially thought macros are just text replacement, so if i force a string that is equal to an actual function into a macro, it would expand to the function itself, but looks like i was wrong. Is there a way to achieve what i want using a macro, or should i just write a map block?
I initially thought macros are just text replacement,
That's your problem: macros are just text replacement. So if you have:
#define PUSHFUNC(stack, func, value) (pushFloat(func(value), &stack))
And you write:
PUSHFUNC(operands, current, x)
You get:
(pushFloat(current(value), &operands))
And indeed, you have no function named current. Macros are expanded before your code compiles; the preprocessor has no knowledge of the content of your variables.
If you really want to avoid a long chain of if statements, you could implement some sort of table lookup:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <math.h>
typedef double (*floatop)(double x);
typedef struct {
char *name;
floatop operation;
} entry;
double ctg(double);
entry opertable[] = {
{"sin", sin},
{"cos", cos},
{"tan", tan},
{"ctg", ctg},
{"sqrt", sqrt},
{NULL, NULL},
};
double ctg(double x) {
return 1. / tan(x);
}
floatop findop(char *name) {
int i;
for (i=0; opertable[i].name; i++) {
if (strcmp(opertable[i].name, name) == 0) {
return opertable[i].operation;
}
}
}
int main() {
float x = 4;
printf("sin(%f) = %f\n", x, findop("sin")(x));
printf("sqrt(%f) = %f\n", x, findop("sqrt")(x));
printf("tan(%f) = %f\n", x, findop("tan")(x));
printf("ctg(%f) = %f\n", x, findop("ctg")(x));
}
...but this requires that all of your functions take the same arguments, so for things like ctg you would need to add a helper function. You also need to decide if the increased complexity of the table lookup makes sense: it really depends on how many different operation names you expect to implement.
The output of the above code is:
sin(4.000000) = -0.756802
sqrt(4.000000) = 2.000000
tan(4.000000) = 1.157821
ctg(4.000000) = 0.863691
Is there a way to achieve what i want using a macro, or should i just write a map block?
I would recommend using an enum containing symbols for all the functions you might want to call, and using that in a switch-case block, instead of comparing a bunch of strings. Here's a very brief sample that only uses some of the functions you refer to...
enum which_func { SIN, COS, TAN, };
enum which_func which = SIN;
switch (which) {
case SIN:
pushFloat(sin(x), &operands);
break;
case COS:
pushFloat(cos(x), &operands);
break;
case TAN:
pushFloat(tan(x), &operands);
break;
default:
assert(false); // shouldn't be reachable if enum value is well-defined
}
This version will be easier to maintain in the long run, more efficient to execute and possibly more robust to logic errors (there are some compiler warnings that you can enable which will warn you if you're not handling all enum values, which can help you catch missed cases in your logic).
To add to what other answers said, what you can do is to make a macro that expands to the "basic block" of your if chain, avoiding some repetitions thanks to the stringizing operator:
#define HANDLE_FN_EXPR(fn, expr) \
else if(!strcmp(current, #fn)) \
pushFloat((expr), &operands)
#define HANDLE_FN(fn) \
HANDLE_FN_EXPR(fn, fn(x))
Then you can do
if(0);
HANDLE_FN(sin);
HANDLE_FN(cos);
HANDLE_FN(tan);
HANDLE_FN_EXPR(ctg, 1./tan(x));
HANDLE_FN(ln);
HANDLE_FN(sqrt);
Macros do in fact do text replacement. Given your macro definition, this:
PUSHFUNC(operands, current, x)
expands to this:
(pushFloat(current(x), &operands))
So as you can see, the text that is being replaced is the name of the variable, not the text that it contains.
And even if this did work as you expected, it wouldn't be able to properly handle the 1. / tan(x) case.
This means there isn't really a better way to do what you want.
Why not create some objects for each function type? I know, this is C not C++, but the idea will still work. First, create the function object type:-
typedef struct _Function
{
char *name;
float (*function) (float argument);
} Function;arg
And now create an array of function objects:-
Function functions [] =
{
{ "sin", sin },
{ "cos", cos }
// and so on
};
where the functions are defined:-
float sin(float x)
{
return 0; // put correct code here
}
float cos(float x)
{
return 0; // put correct code here
}
Finally, parse the input:-
for (int i = 0; i < sizeof functions / sizeof functions[0]; ++i)
{
if (strcmp(functions[i].name, current) == 0)
{
pushFloat(functions[i].function(arg)); // add operands!
break;
}
}
I find using enums for stuff like this very hard to maintain! Adding new functions means going through the code to find cases where the enum is used and updating it prone to errors (like missing a place!).
All because it's not C++, doesn't mean you can't use objects! It's just there's no language support for it so you have to do a bit more work (and, yeah, there are features missing!)

Using a switch to map function pointers to strings

I'm working on a network service that based on commands it receives over the network, it has workers perform different jobs. I want to have a log entry for every time a certain worker is tasked with doing some job.
I have a function (say function_caller) which, among other things, calls another function which it receives its pointer as an argument. I'd like to have my logger notify what kind of function function_caller calls.
Originally I wanted the function_caller to receive some enum instead of a function pointer, provide the enum to the logger, and then use a helper function which returns a suitable pointer based on the enum. However, function_caller is already deeply tangled in the codebase I'm working on, and it looks like it would be a lot of work to refactor all the functions that call function_caller to choose the right enum and use a new argument.
So my next idea was having a switch that for every function pointer will have some string representation of, but I've never stumbled upon something like that (and struggled to find anyone even mentioning such an idea on Google), so I have a feeling I might be missing some serious downsides to this option.
The only significant problem I see is that every developer that decides to pass a new kind of function pointer to function_caller will have to somehow know to update the switch, otherwise it will fail.
Am I missing anything else? Or maybe there's some other approach I should consider?
How about something like this? Instead of a switch, store a table of functions and their name strings. The table can even be kept dynamically updated, unlike a switch case. You will not need to walk along the edge of the standard as well!
#include <stdio.h>
typedef void (*callback_t) (void);
void first (void) { printf("%d", 1); };
void second (void) { printf("%d", 2); };
void third (void) { printf("%d", 3); };
typedef struct fntable_t
{
callback_t fn;
char *name;
} fntable_t;
fntable_t fntable[] =
{
{ first, "first" },
{ second, "second" },
{ third, "third" }
};
char* log_str(callback_t c)
{
for(int i = 0; i < sizeof(fntable) / sizeof(fntable_t); i++)
{
if(fntable[i].fn == c)
return fntable[i].name;
}
return "unknown";
}
void function_caller(callback_t c)
{
printf("%s",log_str(c));
c();
}
int main(void)
{
function_caller(first);
function_caller(second);
function_caller(third);
return 0;
}
You could replace function_caller with a wrapper macro of the same name that calls the renamed function function_caller_internal which gets an additional string argument. The wrapper macro can then pass an additional stringified function name.
This works only if function_caller is always called with a function name, not a function pointer variable.
Example:
#include <stdio.h>
static void funcA(void)
{
printf("This is funcA\n");
}
static void funcB(void)
{
printf("This is funcB\n");
}
/* renamed function gets an additional string argument */
static void function_caller_internal(void (*func)(void), const char *name)
{
printf("calling %s\n", name);
func();
}
/* wrapper macro stringifies the function name to pass it the additional argument */
#define function_caller(func) function_caller_internal(func, #func)
int main(void)
{
/* unchanged calls */
function_caller(funcA);
function_caller(funcB);
return 0;
}
This prints
calling funcA
This is funcA
calling funcB
This is funcB
If you can change the API of the functions, then consider using __func__ to get the textual name of each function. If you can have a function pointer type along the lines of this:
typedef void func_t (const char** name);
Then you can have each function return its name to the caller.
void foo (const char** name)
{
/* do foo stuff here */
*name = __func__;
}
void bar (const char** name)
{
/* do bar stuff here */
*name = __func__;
}
Example:
#include <stdio.h>
typedef void func_t (const char** name);
void foo (const char** name)
{
/* do foo stuff here */
*name = __func__;
}
void bar (const char** name)
{
/* do bar stuff here */
*name = __func__;
}
const char* function_caller (func_t* func, const char** name)
{
func(name);
return *name;
}
int main(void)
{
static func_t*const func [] =
{
foo,
bar,
};
const char* name;
for(size_t i=0; i<sizeof func/sizeof *func; i++)
{
puts( function_caller(func[i], &name) );
}
}
Assuming your codebase has sane variable names and function names, you can add a char * argument to your function caller:
void function_caller(char *name, int fpnt());
and then provide a macro:
#define function_caller_autoname(fpnt) function_caller(#fpnt, fpnt)
(Or, for spaghetti code, you can provide a macro with the same name as the function).
The #fpnt will be expanded by the proceprocessor to a string literal with the function name.
Then when your codebase called:
function_caller(some_function)
refactor it to:
function_caller_autoname(some_function)
# will be expanded to by the processor:
# function_caller("some_function", some_function)
or refactor it manually to provide the name/identificator/description of the function:
function_caller("Some function: ", some_function)
That way you can pass a custom string that describes the function along with the pointer. Also, each developer can pass a custom description string.

Concatenate two functions into one in C

How can I concatenate (or merge) two functions that take no arguments and return nothing into one function? In JavaScript I would do this:
function f1() {
console.log("f1 called");
}
function f2() {
console.log("f2 called");
}
function function_concat(fa, fb) {
var final = function() {
fa();
fb();
};
return final;
}
var merged = function_concat(fa, fb);
merged();
In C, this is what I have:
#include <stdio.h>
#include <stdlib.h>
typedef void (*fptr)(void);
void f1() {
printf("f1 called");
}
void f2() {
printf("f2 called");
}
fptr function_concat(fa, fb) {
// What to do here??
}
int main(int argc, const char **argv) {
fptr merged = function_concat(f1, f2);
fptr();
}
I know I'll have to return a static pointer, but I can't define a function in a function in C which makes it hard to create new functions if I'm already in a function. Does anybody know a way to do this?
You can't define function at runtime in C, so you're only option is to implement some sort of proxy. You can use global variables to refer to the function pointers, but to give an implicit answer, you can't really emulate this in C.
If you ever need to change the interface of fa_ and fb_ you'll need to call function_concat again, or set the global variables directly, but at that point you wouldn't need the proxy function.
static fptr fa_, fb_;
void function_concat_proxy() {
fa_();
fb_();
}
fptr function_concat(fptr fa, fptr fb) {
fa_ = fp;
fb_ = fb;
return function_concat_proxy;
}
Let me preface by saying that trying to emulate the behavior of a language which treats functions as first class citizens is a, to say the least, weird request.
Alternatively, one thing you could create a new typedef for a type that takes two function pointers and then call it:
typedef void (*mptr)(fptr, fptr);
With function_concat looking like:
void function_concat(fptr fa, fptr fb) {
fa();
fb();
}
and main:
int main(int argc, const char **argv) {
mptr merged = function_concat;
merged(f1, f2);
}
Which is similar to just calling function_concat(f1, f2) only via a function pointer now. Apparently not exactly what you're looking for but, alas, I'll leave it here for reference.
You cannot do this in c. What you can do is to call your 2 functions in the function_concat :
void function_concat(fa, fb) {
fa();
fb();
}

Pointer to a function via string

I have an issue with a customer. He's asking me to set up a DB table with key/values where the values are names of C functions.
He wants me to build a generic executable that will take the records of that table and call the functions stored into a C library. He wants to be able to insert or update new pairs of key/values and without modifying the executable, be able to change the function called.
As an example, I wil l post now something very similar:
int sum(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int (*funcion) (int,int);
{
...
funcion = (void*)"sum";
x = funcion(4,3);
funcion = (void*)"sub";
x = funcion(4,3);
}
Is this going to work?
Thanks!
You need a "lookup table".
The problem is that you need to define all functions which could be called before compilation. In order to add new functions you need to change the code. But if thats ok for you this should do the job.
#include <stdio.h>
#include <string.h>
typedef enum
{
_printf,
_scanf,
} functions;
void *get_function_ptr(int func)
{
switch (func)
{
case _printf: return &printf;
case _scanf: return &scanf;
default: return NULL;
}
}
int main(int argc, char **argv)
{
if (strcmp(argv[1], "printf") == 0)
{
void (*ptr)(char *, char *) = get_function_ptr(_printf);
(*ptr)("%s", "hi there");
}
}
Another way would, as in the comment above said, a dynamic linked library, but then you are OS dependend.

How do I get SWIG to automatically wrap an emulated "this" pointer to a C struct?

I've got a simple C "class" I have implemented, using function pointers in a struct to implement the member functions, and passing a pointer to the struct as the first argument to each function, similar to the implicit "this" pointer in C++.
%module mytest
%{
typedef struct mytest mytest;
struct mytest {
int data;
int (*func1)(mytest *,int);
void (*func2)(mytest *,int);
};
int f1(mytest *me,int n) { return me->data + n; }
void f2(mytest *me,int n) { me->data += n; }
mytest *mytestNew(int n) {
mytest *me = (mytest*) malloc(sizeof(mytest));
me->data = n;
me->func1 = f1;
me->func2 = f2;
return me;
}
%}
typedef struct mytest mytest;
struct mytest {
int data;
int func1(mytest *,int);
void func2(mytest *,int);
};
extern mytest *mytestNew(int n);
Now my problem is, when the interface is created to whatever language I choose in the front end, I wind up having to explicitly pass the "this" pointer to the object, even though the language itself supports hiding this.
For instance, suppose I choose Python. I have to do something like this:
from mytest import *
m = mytestNew(1)
m.func1(m,0)
Where what I really want is to do it like this:
from mytest import *
m = mytestNew(1)
m.func1(0)
I know I could just write some wrapping code, but for my actual project I have a lot of functions in a lot of objects of existing C code, and multiplying this by every language that I want to support, this is just too much work! Is there some way to get SWIG to do this automatically?
You can do this in a language neutral way in SWIG with just two typemaps provided you name the parameter something consistent in the SWIG interface as well as the definitions to allow the typemaps to be applied selectively. (Unless you wanted all pointers to mytest to become "this" pointers by default of course)
The typemaps you need are:
// Make sure the wraqpped function doesn't expect an input for this:
%typemap(in,numinputs=0) mytest *me "$1=NULL;"
// Slightly abuse check typemap, but it needs to happen after the rest of the arguments have been set:
%typemap(check) mytest *me {
$1 = arg1;
}
The check typemap isn't really intended for use like this, but it's the easiest way to get the code to be injected after the arguments have been extracted from the target language and before the actual call is made.
You can also simplify the module with the help of a macro to avoid having to write and keep in sync the mapping between the function pointers and the members trick. I ended up with test.h as:
#ifdef SWIG
#define MEMBER(name, args) name args
#else
#define MEMBER(name, args) (*name) args
#endif
typedef struct mytest mytest;
struct mytest {
int data;
int MEMBER(func1,(mytest *me,int));
void MEMBER(func2,(mytest *me,int));
};
And the corresponding interface file (test.i):
%module test
%{
#include "test.h"
static int f1(mytest *me,int n) { return me->data + n; }
static void f2(mytest *me,int n) { me->data += n; }
%}
%extend mytest {
mytest(int n) {
$self->data = n;
$self->func1 = f1;
$self->func2 = f2;
}
}
%typemap(in,numinputs=0) mytest *me "$1=NULL;"
%typemap(check) mytest *me {
$1 = arg1;
}
%include "test.h"
(This interface file provides a constructor that "creates" the "object" exactly how a Java programmer would expect - you can call new and it sets the function pointers behind the scenes)

Resources