Return of nested function

H

hizostudio

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 !
 
N

Nick Keighley

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
 
J

Johannes Bauer

Nick said:
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
 
C

Chris Dollin

Johannes said:
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
 
R

Richard Tobin

Johannes Bauer said:
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
 
B

Ben Bacarisse

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,235
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top