1

I am building a app with lots of files that use the same "main" functionality

for example:

file1 as 3 functions called: doX, doY, doZ file2 as 1 function called: abc file3 as 10 functions called: a1, a2, a3 etc...

i have a main program that process these functions in order to generate and calculate correct data.

the problem i have is the "main" program does not know which functions to run so i was thinking to create a common function for all my files that will return the list of the functions to run in a specific order

but for some reason it does not work

heres my sample code

  // in main.h
  #include <stdio.h>

  // in file1.c
  // #include ...
  int doX() {
    // do stuff
    return 1;
  }

  int doY() {
    // do stuff
    return 1;
  }

  int * get_tasks() {

    int (*task[2])() = { };
    int id = 0;

    id++; task[id] = doX;
    id++; task[id] = doY;

    return *task;
  }

  // main.c
  #include "main.h"
  int main () {

    int * pl;
    int i, success = 0;

    printf("do stuff");
    pl = get_tasks();

    for(i = 0; i < 2; i++) {
      success += *(pl[i])();
    }

    printf("success = %d", success);

  }

when i run: gcc *.c

i get:

test.c: In function ‘get_tasks’:
test.c:24:3: warning: return from incompatible pointer type [enabled by default]
   return *task;
   ^
test.c: In function ‘main’:
test.c:38:24: error: called object is not a function or function pointer
     success += *(pl[i])();
                     ^

how can i fix this?

3
  • Pointer to function is not int* (return type of get_tasks)... Commented May 19, 2015 at 14:22
  • 1
    Your code has many problem, for starters you should not return a pointer to a local variable. And you are not returning function pointers. Commented May 19, 2015 at 14:24
  • @AdrianoRepetti ??? from what you said: Pointer to function is not int* (return type of get_tasks) then what I should use? Commented May 19, 2015 at 14:24

3 Answers 3

3

The correct way of doing it, is

typedef int (*FunctionType)(void);

and then declare your function pointers as

FunctionType functionPointer;

Also you had more problems

  1. Don't return a pointer to a local variable.
  2. You increment id before task[id] = ... which also you do with a really confusing style, that has 2 problems

    1. You can use the pre-increment operator, like

      task[++id] = ...;
      
    2. It would still be wrong, because arrays are 0-base indexed, so by accessing task[1] you are actually at the end of the array, task[2] would cause undefined behavior.

This is a working version of your code

#include <stdio.h>

typedef int (*FunctionType)(void);

int doX(void) {
    return 1;
}

int doY(void) {
    return 1;
}

void gettasks(FunctionType task[2])
{
    int id = 0;

    task[id++] = doX;
    task[id++] = doY;
}

int main(void) {
    FunctionType tasks[2];
    int i, success = 0;

    printf("do stuff\n");
    gettasks(tasks);

    for(i = 0; i < 2; i++) {
      success += tasks[i]();
    }
    printf("success = %d", success);
    return 0;
}
Sign up to request clarification or add additional context in comments.

4 Comments

How would you pass a different number : FunctionType tasks[2]; each files has different number of tasks to run?
@PatREllery just gettasks(size_t count, FunctionType task[count]);, you need to make sure that your compiler supports VLA's otherwise use dynamic memory, but for that if you don't know how, then you will need to ask another question.
Thanks, sorry but I think defining that will not work in the "MAIN". you defined first FunctionType tasks[2]; THEN you calling gettasks...
You should not think about that, you should read about automatic variables and scope, if you do it without malloc() and without passing the array to gettasks() then you will cause undefined behavior.
2

A function returning a pointer to a function looks like:

int(*)()function()

rather than

int* function()

as in your code. Alternatively, you can use a typedef:

typedef int(*functype)();

functype function();

which makes things slightly less confusing.

You can't return a pointer to a stack variable, though; that pointer will point to invalid memory by the time you return. You have to use malloc() or some such (and then remember not to forget to clean up). Alternatively, don't return a pointer, return a struct instead:

struct fptrs_struct {
    int(*open)();
    int(*close)();
    // ...
}

struct fptrs_struct function() {
    struct fptrs_struct retval;
    retval.open = foo;
    retval.close = bar;
    // ...
    return retval;
}

This works, and doesn't require malloc or some such (but involves slightly more copying on return).

Congratulations, you're now doing OO in C. Maybe use a library for that (hint: gobject), or better yet, switch to a language which actually supports object orientation -- like Objective-C or C++.

2 Comments

@WouterVerhelst well how can I put this in my code first, i get errors, let me start over ... how can I pass the number of tasks? why close? open?
I was assuming the main program was going to do more than just call each and every function in turn; if it does that, I would suggest you just create a single function in each file that calls the functions in turn and return a function pointer to that. Else, you might have a function "open" that opens something, a function "close" that closes that again, a function "do_stuff" that does stuff with what you've opened, etc; what the exact names would be depends on your problem, I can't answer that. Returning an array of function pointers and then calling them in turn smells of bad design, though.
1

I think, by writing

int (*task[2])() = { };
int id = 0;

id++; task[id] = doX;
id++; task[id] = doY;

you're trying to access index 1 and 2, which is a memory overrun and cause for undefined behaviour.

After that, task[2] is a local to get_tasks()(). You should not be returning the address of the same because, once get_tasks() finishes, task[2] ceases to exist. returning the address and using the same in the caller again leads to undefined behaviour.

That said, using a typedef for function pointers is quite handy and more readable, in my opinion.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.