Return of nested function

Discussion in 'C Programming' started by hizostudio@gmail.com, Jul 15, 2008.

  1. Guest

    Hi there,


    I have a problem.
    I'd like to make a function (*callback_func*), which returns another
    one (*callback*) (according to the arguments of the first one), in
    order to give it to another function (*get*), which accepts only a
    precise type of function and will use it as a callback function.

    I don't know if it's very speaking for you, so I'll try to give you an
    example of such functions.

    - I use GCC (and its extension for the nested functions)
    - I didn't write the prototypes

    ---------------------------------------------------------------
    #include <stdlib.h>
    #include <stdbool.h>

    bool get_first_int(int * const ptr, const int list[], const size_t
    size, bool (*func)(const int))
    {
    bool found;
    unsigned int i;

    for(found = false, i = 0; !found && i < size; i++)
    {
    if(func(list))
    {
    *ptr = list, found = true;
    }
    }

    return found;
    }

    bool is_odd(const int i)
    {
    return i & 1;
    }

    bool is_multiple_of_3(const int i)
    {
    return is_multiple_of(3)(i);
    }

    bool (*is_multiple_of(const int multiple))(const int)
    {
    bool func(const int i)
    {
    div_t d = div(i, multiple);

    return d.quot != 0 && d.rem == 0;
    }

    return func;
    }
    ---------------------------------------------------------------

    Here, *callback_func* is "is_multiple_of", *callback* are "is_odd" or
    "is_multiple_of_3" and *get* is "get_first_int".

    Then, I'd like to write :

    ---------------------------------------------------------------
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>

    int main(void)
    {
    int res, list[7] = {0, -6, 2, 3, 6, 1, 5};
    bool found;

    found = get_first_int(&res, list, sizeof(list) / sizeof(*list),
    is_multiple_of(5));

    if(found)
    {
    printf("First match is '%i'\n", res);
    }
    else
    {
    puts("No match...");
    }

    return EXIT_SUCCESS;
    }
    ---------------------------------------------------------------

    I want to give as callback function, to *get*, directly the function
    returned by *callback_func*, and not a global function (such as
    "is_multiple_of_3").

    But, the problem is that it won't work, since the function returned by
    *callback_func* is local and thus the memory zone is inaccessible in
    my *get* function.
    So, I'd like to know how to fix this, properly.

    Thanks in advance !


    Cordially,
    Hiz0


    PS: Sorry for my bad english, I'm french !
     
    , Jul 15, 2008
    #1
    1. Advertising

  2. On 15 Jul, 10:47, wrote:

    > I have a problem.
    > I'd like to make a function (*callback_func*), which returns another
    > one (*callback*) (according to the arguments of the first one), in
    > order to give it to another function (*get*), which accepts only a
    > precise type of function and will use it as a callback function.


    something like:

    typedef void (*Callback) (int);

    Callback callback_func(int n)
    {
    switch (n)
    {
    case 1:
    return is_odd;
    case 2:
    return divisible_by_3;
    }
    }

    void get (Callback cb)
    {
    cb (99);
    }

    int main(void)
    {
    get (callback_func(1));
    }



    > I don't know if it's very speaking for you, so I'll try to give you an
    > example of such functions.
    >
    > - I use GCC (and its extension for the nested functions)


    ah. As you note this is a gcc extension. You need to ask on
    a gcc group for the exact semantics of their nested functions

    > - I didn't write the prototypes
    >
    > ---------------------------------------------------------------
    > #include <stdlib.h>
    > #include <stdbool.h>
    >
    > bool get_first_int(int * const ptr, const int list[], const size_t
    > size, bool (*func)(const int))
    > {
    >         bool found;
    >         unsigned int i;
    >
    >         for(found = false, i = 0; !found && i < size; i++)
    >         {
    >                 if(func(list))
    >                 {
    >                         *ptr = list, found = true;
    >                 }
    >         }
    >
    >         return found;
    >
    > }
    >
    > bool is_odd(const int i)
    > {
    >         return i & 1;
    >
    > }
    >
    > bool is_multiple_of_3(const int i)
    > {
    >         return is_multiple_of(3)(i);
    >
    > }
    >
    > bool (*is_multiple_of(const int multiple))(const int)


    I'd probably throw in some typedefs as I find ptrs-to-functions
    pretty unreadable.

    > {
    >         bool func(const int i)
    >         {
    >                 div_t d = div(i, multiple);
    >
    >                 return d.quot != 0 && d.rem == 0;
    >         }
    >
    >         return func;}
    >
    > ---------------------------------------------------------------
    >
    > Here, *callback_func* is "is_multiple_of", *callback* are "is_odd" or
    > "is_multiple_of_3" and *get* is "get_first_int".
    >
    > Then, I'd like to write :
    >
    > ---------------------------------------------------------------
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <stdbool.h>
    >
    > int main(void)
    > {
    >         int res, list[7] = {0, -6, 2, 3, 6, 1, 5};
    >         bool found;
    >
    >         found = get_first_int(&res, list, sizeof(list) / sizeof(*list),
    > is_multiple_of(5));
    >
    >         if(found)
    >         {
    >                 printf("First match is '%i'\n", res);
    >         }
    >         else
    >         {
    >                 puts("No match...");
    >         }
    >
    >         return EXIT_SUCCESS;}
    >
    > ---------------------------------------------------------------
    >
    > I want to give as callback function, to *get*, directly the function
    > returned by *callback_func*, and not a global function (such as
    > "is_multiple_of_3").
    >
    > But, the problem is that it won't work, since the function returned by
    > *callback_func* is local and thus the memory zone is inaccessible in
    > my *get* function.
    > So, I'd like to know how to fix this, properly.


    don't use nested functions? Again I'm afraid I don't know
    the semantics of gcc's nexted functions. Now some languages
    would let you do what you do above and others (I believe)
    wouldn't.

    I'd probably bodge around it with global functions. But
    I can't say how without knowing more about what you are
    trying to do. You *look* like you are trying to do
    functional programming in C. Perhaps another language
    might be a better idea?


    > PS: Sorry for my bad english, I'm french !


    your english is fine


    --
    Nick Keighley

    There are only two ways to live your life.
    One is as though nothing is a miracle.
    The other is as though everything is a miracle.
    Albert Einstein
     
    Nick Keighley, Jul 15, 2008
    #2
    1. Advertising

  3. Nick Keighley schrieb:

    >> - I use GCC (and its extension for the nested functions)

    >
    > ah. As you note this is a gcc extension. You need to ask on
    > a gcc group for the exact semantics of their nested functions


    Why is there actually a *need* for nested functions? If functionality of
    subfunctions which are only locally visible is desired, why not put the
    nesting function parent and its nested children all in one module,
    declare the children static - voila. Std-C.

    Regards,
    Johannes

    --
    "Wer etwas kritisiert muss es noch lange nicht selber besser können. Es
    reicht zu wissen, daß andere es besser können und andere es auch
    besser machen um einen Vergleich zu bringen." - Wolfgang Gerber
    in de.sci.electronics <47fa8447$0$11545$>
     
    Johannes Bauer, Jul 15, 2008
    #3
  4. Chris Dollin Guest

    Johannes Bauer wrote:

    > Nick Keighley schrieb:
    >
    >>> - I use GCC (and its extension for the nested functions)

    >>
    >> ah. As you note this is a gcc extension. You need to ask on
    >> a gcc group for the exact semantics of their nested functions

    >
    > Why is there actually a *need* for nested functions? If functionality of
    > subfunctions which are only locally visible is desired, why not put the
    > nesting function parent and its nested children all in one module,
    > declare the children static - voila. Std-C.


    It's possible (even likely) that the GCC semantics is more powerful
    than this would allow. For example, it might implement Pascal-style
    nesting, where functions can refer to the locals of the functions
    they are nested in while those functions are still executing.

    /Clearly/ you can fabricate code to get round this, unless (as
    you likely will) you have to pass your function-plus-fabrications
    through a function-pointer-sized-and-typed slot. Oops.

    --
    If you read the signature, the signature reads you. - eh

    Hewlett-Packard Limited Cain Road, Bracknell, registered
    no:
    registered office: Berks RG12 1HN 690597
    England
     
    Chris Dollin, Jul 15, 2008
    #4
  5. In article <>,
    Johannes Bauer <> wrote:

    >Why is there actually a *need* for nested functions? If functionality of
    >subfunctions which are only locally visible is desired, why not put the
    >nesting function parent and its nested children all in one module,
    >declare the children static - voila. Std-C.


    Is there actually a *need* for local variables? If functionality of
    variables which are only locally visible is desired, why not put the
    function in a file by itself and declare the variables static at file
    scope - voila.

    The point, of course, is that nested functions can do more than
    control the visibility of the function name. They let you create
    closures - instances of functions that are "closed" over the bindings
    of variables in enclosing scopes.

    [Yes, you could have an implementation of nested functions that didn't
    provide this, just as you could have an implementation of local
    variables that didn't make recursive calls work. Then they really
    wouldn't be much use.]

    -- Richard
    --
    Please remember to mention me / in tapes you leave behind.
     
    Richard Tobin, Jul 15, 2008
    #5
  6. writes:

    > I have a problem.
    > I'd like to make a function (*callback_func*), which returns another
    > one (*callback*) (according to the arguments of the first one), in
    > order to give it to another function (*get*), which accepts only a
    > precise type of function and will use it as a callback function.


    You can't do this in C (even using the GNU extension you tried). It
    may be an idea to rethink the whole plan. Do you need to use C? Can
    you do things another way?

    You can get close to what you want by packaging up the data with a
    pointer to a function that uses it. See below for an example.

    > I don't know if it's very speaking for you, so I'll try to give you an
    > example of such functions.
    >
    > - I use GCC (and its extension for the nested functions)


    The manual[1] says:

    "If you try to call the nested function through its address after
    the containing function has exited, all hell will break loose."

    You are doing just that!

    Here is one idea:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>

    struct BinaryTest {
    bool (*binary_op)(int, int);
    int arg;
    };

    bool call_test(struct BinaryTest *tp, int i)
    {
    return tp->binary_op(tp->arg, i);
    }

    bool get_first_int(int *ptr, const int *list, size_t size,
    struct BinaryTest *test)
    {
    size_t i;
    for (i = 0; i < size; i++)
    if (call_test(test, list)) {
    *ptr = list;
    return true;
    }
    return false;
    }

    static bool multiple_of(int a, int b)
    {
    div_t d = div(b, a);
    return d.quot != 0 && d.rem == 0;
    }

    int main(void)
    {
    struct BinaryTest multiple_of_5 = { multiple_of, 5 };
    int res, list[7] = {0, -6, 2, 3, 6, 1, 5};

    if (get_first_int(&res, list, sizeof(list) / sizeof(*list),
    &multiple_of_5))
    printf("First match is '%d'\n", res);
    else
    puts("No match...");
    return EXIT_SUCCESS;
    }

    Of course, there is nothing to stop you either writing a function that
    returns the test:

    struct BinaryTest make_multiple_test(int m)
    {
    return (struct BinaryTest){multiple_of, m}; // C99 alert!
    }


    [1] http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Nested-Functions.html#Nested-Functions
    --
    Ben.
     
    Ben Bacarisse, Jul 15, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Russ Perry Jr
    Replies:
    2
    Views:
    4,145
    Russ Perry Jr
    Aug 20, 2004
  2. Seong-Kook Shin
    Replies:
    1
    Views:
    495
    Richard Bos
    Jun 18, 2004
  3. Greenhorn
    Replies:
    15
    Views:
    831
    Keith Thompson
    Mar 6, 2005
  4. Replies:
    4
    Views:
    550
    James Kanze
    Jul 22, 2008
  5. Richard A. DeVenezia

    Nested function X vs. nested varX = function

    Richard A. DeVenezia, Sep 8, 2003, in forum: Javascript
    Replies:
    1
    Views:
    133
    Code Ronin
    Sep 9, 2003
Loading...

Share This Page