I have background with high level languages, such as Java/Kotlin/Scala. Now I need to create a C library, but it's pretty hard for me to work without closures.
There is the nice extension in GCC, called "nested functions", that (if I correctly understood) is exactly what I need. Also the Apple "blocks" extension looks interesting. But I need a code, that will work with any compiler.
Does any existing solution present? I've seen some projects, that allow generating C code: https://github.com/dbohdan/compilers-targeting-c. But I really don't need another language, just one feature - closures. (I think that it hard to maintain completely different language and result C code will be not optimized).
UPD Some explanation, why do I need closures.
Let say we have some function, connect(void (*on_failed_callback)());
. It manages a connection in some way, and when the connection is lost, it calls the callback. And it takes 0 arguments, but I want to create some function that will bring some data with callback. If I've correctly understood, the most common used solution is to pass the callback with some arg connect(void (*on_failed_callback)(void *callback_arg), void* arg);
. But it leads to a boilerplate code, that can be fixed by nested functions.
So next code:
void connect(void (*on_failed_callback)(void* arg), void* arg) {
...
on_failed_callback(arg);
}
void print_error(char* error) {
printf(error);
}
void main() {
char *msg = "Failed connection";
...
connect(print_error, msg);
}
Can be simplified to next:
void connect(void (*on_failed_callback)()) {
...
on_failed_callback();
}
void print_error(char* error) {
printf(error);
}
void main() {
char* msg = "Failed connection";
...
void callback() {
print_error(msg);
}
connect(callback);
}
I mean, I want some tool/app, that analyzes my code with closures/nested functions and generates pure ANSI C code.
For the specific example you have asked about there is an approach with C that achieves something similar to a closure in that it packages a function pointer with the data needed to be used with the function.
typedef struct {
char sBuff[128]; // data for the function to use
void (* func) (char* error); // pointer to function to execute
} ErrorMsg;
void connect(ErrorMsg myMsg) {
...
myMsg.func(myMsg.sBuff); // call the function with the packaged data
}
// the function that we will be encapsulating with the data to be
// used.
void print_error(char* error) {
printf(error);
}
void main() {
ErrorMsg msg = {"Failed connection", print_error} ;
…
connect(msg); // invoke our function package and its data.
}
And if at the time that the function package is used, you would like to add additional data, you could do so along the lines of the following.
typedef struct {
char sBuff[128]; // packaged data for the function to use
void (* func) (char* error, int iExtra); // pointer to function to execute
} ErrorMsg;
void connect(ErrorMsg myMsg) {
...
myMsg.func(myMsg.sBuff, errno); // call the function with the packaged data and extra info
}
// the function that we will be encapsulating with the data to be
// used.
void print_error(char* error, int iExtra) {
printf(error, iExtra);
}
void main() {
ErrorMsg msg = {"Failed connection: errno %d", print_error} ;
…
connect(msg); // invoke our function package and its data.
}