I'm trying to achieve something I've easily done in dynamic languages, but have no idea how to do in C.
I have a program that needs to call different functions depending on a given string by the user. Each function has a C file of its own.
The easy way to do this is just do if-else-elseif along with strcmp and call each function if it matches.
I want do to something nicer: at the end of each C file holding each significant function, add a "binding" call, a bit like this:
int my_action(char smth[]);
bind_function("myaction", my_action);
Then, in the main program, be able to look up the function for "myaction" string, and if it exists, call it.
I reckon it has to do with mapping a string to a pointer to a function. But, honestly, I have no idea if it's possible or where to start.
Is such a thing possible in C? If it is, then, how can I do it?
You can use call() / apply() to invoke the function immediately. bind() returns a bound function that, when executed later, will have the correct context ("this") for calling the original function. So bind() can be used when the function needs to be called later in certain events when it's useful.
If f is real-valued and f(x) ≤ A for all x in X, then the function is said to be bounded (from) above by A. If f(x) ≥ B for all x in X, then the function is said to be bounded (from) below by B. A real-valued function is bounded if and only if it is bounded from above and below.
bind() The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Bind() Method in JavaScriptThe bind() method is reminiscent of call() and apply() . But instead of executing a function immediately, bind() returns a function that can be executed later on. Let's modify the previous example to use bind() : So calling add. bind(obj, 3, 5) returns a function.
It is possible and the Linux Kernel implements this a lot. See the MACHINE_START macro for example. However, it is very platform, compiler and linker specific. You can't do this in plain, standard C.
Under gcc, I can write something like:
struct function_binding {
const char *name;
int (*func)(char *);
};
#define bind_function(binding_name, func_name) \
static \
__attribute__((section(".funcbind"))) \
__attribute__((used)) \
struct function_binding __##func_name##_binding = { \
.name = binding_name, .func = func_name \
}
int test_func(char *x) {}
bind_function("test_func", test_func);
Which will put all your function bindings into a section called .funcbind
. You'll then want to edit your linker script to add something like this:
function_binding_list = .;
*(.funcbind);
LONG(0); /* Terminate list */
In the file you want to traverse the list in, you can simply use a loop:
extern struct function_binding function_binding_list[];
struct function_binding *curr;
for (curr = function_binding_list; curr->name != NULL; curr++) {
if (!strcmp(curr->name, name)) {
curr->func(args);
break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With