Consider the following C program:
#include <stdio.h>
const int OP_0 = 0;
const int OP_1 = 1;
const int OP_2 = 2;
int op_0(int x) {
return x 2;
}
int op_1(int x) {
return x * 3 1;
}
int op_2(int x) {
return 2 * x * x - 10 * x 5;
}
int compute(int op, int x) {
switch (op) {
case OP_0: return op_0(x);
case OP_1: return op_1(x);
case OP_2: return op_2(x);
}
return 0;
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
It is a very simple program that lets the user select one of 3 operations to perform on an int
input. To use this program, we can compile it with, for instance, gcc program.c -o program
, and then run it with ./program
. That's all obvious. Suppose, though, that we wanted to add another operation:
int op_3(int x) {
return 900 x;
}
If we wanted to use this new operation, we'd need to recompile the entire program. Adding a new operation to this program has O(n)
complexity, and is slow since it requires a complete recompilation.
My question is: is it possible, in C, to let this program add new native operations (without writing an interpreter)? In other words, is it possible to dynamically compile and add op_3 to the C program above, without having to recompile everything?
For illustration purposes, here is an example of what I have in mind:
int compute(int op, int x) {
// the first time it runs, would load `op_N.dll`
// the next time, would use the loaded version
// so, to add a new operation, we just compile
// it and add `op_N.dll` to this directory
Fun op = dynamic_load(op);
return op(x);
}
CodePudding user response:
The only way I can think of is to compile a new dynamic library that is then opened by the program using dlopen()
...
Another way, similar but perhaps more primitive, would be to compile the code into an object file and then load it into a mmaped region with execution permissions, jumping then to it using a function pointer.
CodePudding user response:
Well, what you are asking is the "Open Principle of SOLID". To do so, you need to have a dynamic dlsym
obviously after dlopen
. To have a dynamic dlsym
you need to be able to read header files or a file with the proper function prototypes. Yes, you need to cast function pointers, but the typecast depends upon the types of your parameter list.
Edit:
Hard coding dlsym
means you have to relink your import library to your executable every time you add a function to your shared object.