我可以以某种方式在ANSI C中使用嵌套函数吗?

时间:2019-05-29 13:18:40

标签: c nested-function

我有使用高级语言的背景,例如Java / Kotlin / Scala。现在,我需要创建一个C库,但是没有闭包对我来说很难。

在GCC中有一个很好的扩展,称为“嵌套函数”,(如果我正确理解的话)正是我所需要的。苹果的“ blocks”扩展也很有趣。但是我需要一个可以与任何编译器一起使用的代码。

是否存在任何现有解决方案?我看过一些项目,它们可以生成C代码:https://github.com/dbohdan/compilers-targeting-c。但是我真的不需要另一种语言,只需一个功能-闭包。 (我认为很难保持完全不同的语言,并且结果C代码不会得到优化)。

UPD 一些解释,为什么我需要关闭。

假设我们有一些功能connect(void (*on_failed_callback)());。它以某种方式管理连接,当连接丢失时,它将调用回调。它使用0个参数,但是我想创建一些函数,该函数将通过回调带来一些数据。如果我已正确理解,最常用的解决方案是使用一些arg connect(void (*on_failed_callback)(void *callback_arg), void* arg);传递回调。但这导致了样板代码,可以通过嵌套函数进行固定。

接下来的代码:

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);
}

可以简化为下一个:

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);
}

我的意思是,我想要一些工具/应用程序,用于使用闭包/嵌套函数分析我的代码并生成纯ANSI C代码。

2 个答案:

答案 0 :(得分:3)

对于您所询问的特定示例,使用C的方法可以实现类似于闭包的方式,该方法将函数指针与函数所需的数据一起打包。

() -> value

如果在使用功能包时想添加其他数据,则可以按照以下内容进行。

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.
}

答案 1 :(得分:0)

  

是否存在任何现有解决方案?

这取决于您的意思。标准C不提供闭包,嵌套函数或lambda /块作为语言功能。但是,使用其他语言,您将无法做任何事,而如果没有C语言,您将无法拥有所有这些语言。实际上,具备功能的某些语言本身都是用C实现的。

尤其是,您的第一个示例是通用回调的近似C习惯用法。回调函数接受指向包含所需数据的对象的指针,而回调注册接口接受指向适当对象的指针以及该函数的指针。触发回调后,已注册的数据指针将传递给回调。

顺便说一下,请注意,这是比单独使用闭包更通用的功能,因为回调将在其上进行操作的数据不必在定义函数的范围内。除其他外,这允许提供标准的,可重用的回调实现,其中与特定数据的关联仅在回调注册时进行。如果可以将多个回调与同一个事件同时关联,则它还允许针对同一事件将同一个回调与不同的数据重用。