Thread: Closures in C

  1. #1
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103

    Closures in C

    I tried creating closures in C and I want to know how close to the mark I am.

    First a few notes about what I did.

    1. I used an example which hard coded the types for simplicity. I think you could generalize a solution with macros, it might be messy but I think its doable.
    2. I assumed all data used in closures is allocated on the stack. Basically you have to keep the data valid after the donor function returns so it has to be allocated on the heap.
    3. The closure just displays and increments the data.

    Here's what I tried:

    closure.h
    Code:
    #ifndef CLOSURE__HH
    #define CLOSURE__HH
    #include <stddef.h>
    
    typedef struct closure* CLOSURE_PTR;
    typedef void (*C_FUNC)(CLOSURE_PTR);
    
    typedef struct closure {
      int c_nu;//Basically a number(for debugging) to distinguish each closure
      int data;//Value that the closure uses
      C_FUNC call_closure;
    } CLOSURE;
    
    CLOSURE_PTR create_closure(int, int, C_FUNC);
    void check_allocation(void*);
    
    #endif
    closure.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "closure.h"
    
    void check_allocation(void * ptr) {
      if (!ptr) {
        fputs("Allocation failed!\n", stderr);
        exit(EXIT_FAILURE);
      }
    }
    
    CLOSURE_PTR create_closure(int c_nu, int data, C_FUNC f) {
      CLOSURE_PTR c = malloc(sizeof(*c));
      check_allocation(c);
      c->c_nu = c_nu;
      c->data = data;
      c->call_closure = f;
      return c;
    }
    main.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "closure.h"
    
    void incr_it(CLOSURE_PTR c) {
      if (c) {
        fprintf(stdout, "Closure %d: %d\n", c->c_nu, c->data);
        c->data++;
      }
    }
    
    CLOSURE_PTR test_closure(int nu, int data) {
      CLOSURE_PTR c = create_closure(nu, data, incr_it);
      return c;
    }
    
    int main(int argc, char ** argv) {
      CLOSURE_PTR c1 = test_closure(1, 12);
      c1->call_closure(c1);
      c1->call_closure(c1);
      c1->call_closure(c1);
      CLOSURE_PTR c2 = test_closure(2, 36);
      c2->call_closure(c2);
      c2->call_closure(c2);
      c2->call_closure(c2);
      c1->call_closure(c1);
      c1->call_closure(c1);
      c1->call_closure(c1);
      c2->call_closure(c2);
      c2->call_closure(c2);
      c2->call_closure(c2);
      return EXIT_SUCCESS;
    }
    Output:
    Closure 1: 12
    Closure 1: 13
    Closure 1: 14
    Closure 2: 36
    Closure 2: 37
    Closure 2: 38
    Closure 1: 15
    Closure 1: 16
    Closure 1: 17
    Closure 2: 39
    Closure 2: 40
    Closure 2: 41

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103
    Quote Originally Posted by Salem View Post
    I guess I'm close to the mark.. quoted from wiki

    The idiom is similar to closures in functionality, but not in syntax

Popular pages Recent additions subscribe to a feed

Tags for this Thread