Thread: Using function pointers when argument list of the functions aren't known beforehand

  1. #1
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426

    Using function pointers when argument list of the functions aren't known beforehand

    Hi everyone,

    I am trying to write a generalized function to numerically solve a set of n simultaneous equations in n unknowns, for any integer n. I'd like to pass the individual equations as function pointers to a variable length argument list, like this

    Code:
    void solve_simul( int n, ... ) {/*stuff*/}
    The next n arguments will be pointers to the variables, and the next n after that will be pointers to the functions. I'm planning to have va_arg stick them in an array of function pointers inside solve_simul. If n was 3, the function call would be equivalent to

    Code:
    solve_simul( 3, &x, &y, &z, phi0, phi1, phi2 );
    where each of the phi functions (in the case where n=3) would be like this:

    Code:
    double phi0( double x, double y, double z ) {/*stuff*/}
    My problem is how to declare the function pointers inside the solve_simul function. It doesn't know beforehand how many variables the phi functions take, so how can I specify what type they are?
    Code:
    while(!asleep) {
       sheep++;
    }

  2. #2
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    This is a guess - Give it a go: And if it works, it works; if it doesn't, it doesn't.

    Try and make a typedef for a function pointer

    Code:
    typedef (*f_pointer)(double x, double y, double z);
    And then assign the va_arg(argptr, f_pointer) to a local function pointer and handle them individually
    Fact - Beethoven wrote his first symphony in C

  3. #3
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426
    Yes, but this will only work in the case of three equations in three unknowns. Let's say the next person comes along and wants to solve a system of five. The it would have to be

    Code:
    typdef (*f_pointer)(double v, double w, double x, double y, double z);
    and there's no way of knowing how many equations and unknowns beforehand.
    Code:
    while(!asleep) {
       sheep++;
    }

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Think about it. How are you going to call your phi0 function from within solve_simul? You can't unpack the variable args into an argument list. However, you could probably pass the va_list itself.

    But still, why don't you just use arrays?
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Quote Originally Posted by TheBigH View Post
    Yes, but this will only work in the case of three equations in three unknowns. Let's say the next person comes along and wants to solve a system of five. The it would have to be

    Code:
    typdef (*f_pointer)(double v, double w, double x, double y, double z);
    and there's no way of knowing how many equations and unknowns beforehand.
    What's wrong with using the va_arg system in the function pointer? Just make sure that your functions that you enter are handling the inputs in a "va_arg" way

    Code:
    typedef (*f_pointer)(int n_of_inputs, ...)
    Fact - Beethoven wrote his first symphony in C

  6. #6
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426
    Quote Originally Posted by oogabooga View Post
    Think about it. How are you going to call your phi0 function from within solve_simul? You can't unpack the variable args into an argument list.
    I'm not sure I understand. I should be able to call phi0 from within solve_simul if I have a pointer to it, and pointers to all the variables it needs. And I do have all those things, but I don't know the length of phi0's argument list before I call solve_simul.

    But still, why don't you just use arrays?
    You mean, something like this:
    Code:
    void solve_simul( int n, double **variables, double (*phis( int, double * ))[] ) {/*something like this?*/}
    Well, I've probably got the declaration slightly wrong but the point is to pass an array of pointers to functions that take arrays of their dependent variables. Yeah, that might work. Cheers.
    This stuff makes my brain hurt.
    Code:
    while(!asleep) {
       sheep++;
    }

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    Quote Originally Posted by Click_here View Post
    What's wrong with using the va_arg system in the function pointer? Just make sure that your functions that you enter are handling the inputs in a "va_arg" way

    Code:
    typedef (*f_pointer)(int n_of_inputs, ...)
    That's a good suggestion, IMO, but the syntax is wrong. You will have to call va_start in the solve_simul function, copy the va_list with va_copy for each function call, pass the copy to the function, and then call va_end on the copy each time.
    Code:
    typedef (*f_pointer)(int, va_list *);
    (I haven't used stdarg for quite some time so this might not be 100% correct.)
    Last edited by christop; 10-04-2012 at 10:48 PM. Reason: fiks speling

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by TheBigH View Post
    I'm not sure I understand. I should be able to call phi0 from within solve_simul if I have a pointer to it, and pointers to all the variables it needs. And I do have all those things, but I don't know the length of phi0's argument list before I call solve_simul.
    You haven't thought it all the way through. Try actually writing code to do that and you'll see the problem.

    This is clearly a job for arrays, not variable argument lists. It's just too ugly with varargs:
    Code:
    #include <stdio.h>
    #include <stdarg.h>
    
    typedef void (*PFUNC)(int n, va_list *va);
    
    void solve_simul(int n, ...) {
        int i;
        va_list va1, va2;
        va_start(va1, n);
        for (i = 0; i < n; i++)   // step va1 past doubles
            va_arg(va1, double);
        for (i = 0; i < n; i++) {
            va_start(va2, n);
            va_arg(va1, PFUNC)(n, &va2);
            va_end(va2);
        }
        va_end(va1);
    }
    
    void f1(int n, va_list *va) {
        int i;
        printf("f1\n");
        for (i = 0; i < n; i++)
            printf("%f\n", va_arg(*va, double));
    }
    
    void f2(int n, va_list *va) {
        int i;
        printf("f2\n");
        for (i = 0; i < n; i++)
            printf("%f\n", va_arg(*va, double));
    }
    
    int main() {
        solve_simul(2, 1.0, 2.0, f1, f2);
        return 0;
    }
    As for using arrays, the declaration of solve_simul would be something like:
    Code:
    void solve_simul(int n, double *vars, double (*phis)(int , double *));
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426
    Okay, so I'm persuaded to not use variable argument lists.

    But shouldn't the declaration be
    Code:
    void solve_simul(int n, double *vars, double *(*phis)(int , double *));
    since I will need an array of function pointers? Thanks for your help.
    Code:
    while(!asleep) {
       sheep++;
    }

  10. #10
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Array of pointers to functions - This might work
    Code:
    Declare f_array as an array of pointers to a function (inputs integer, and pointer to double) returning a double
    double (*f_array[])(int, double *)
    Fact - Beethoven wrote his first symphony in C

  11. #11
    Registered User TheBigH's Avatar
    Join Date
    May 2010
    Location
    Melbourne, Australia
    Posts
    426
    Yep, you're right. Those array square brackets need to be inside the round ones. Thanks.
    Code:
    while(!asleep) {
       sheep++;
    }

  12. #12
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by TheBigH View Post
    Okay, so I'm persuaded to not use variable argument lists. But shouldn't the declaration be ...
    Yep, I didn't do that right. It's always better to use typedefs to simplify these things.
    Code:
    #include <stdio.h>
    
    typedef double (*PFUNC)(int, double*);
    
    double f1(int n, double *vars) {
        int i;
        printf("f1\n");
        for (i = 0; i < n; i++)
            printf("%f\n", vars[i]);
        return 0;
    }
    
    double f2(int n, double *vars) {
        int i;
        printf("f2\n");
        for (i = 0; i < n; i++)
            printf("%f\n", vars[i]);
        return 0;
    }
    
    void solve_simul(int n, double *vars, PFUNC *phis) {
        int i;
        for (i = 0; i < n; i++)
            (phis[i])(n, vars);
    }
    
    int main() {
        double vars[2] = {1.0, 2.0};
        PFUNC phis[2] = {f1, f2};
        solve_simul(2, vars, phis);
        return 0;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 03-19-2012, 08:44 PM
  2. Replies: 2
    Last Post: 03-19-2011, 08:18 PM
  3. Pointer to List Iterator As Function Argument
    By bengreenwood in forum C++ Programming
    Replies: 8
    Last Post: 06-17-2009, 05:30 AM
  4. Replies: 1
    Last Post: 10-21-2007, 07:44 AM
  5. intercepting functions with a variable argument list
    By Peter_Machner in forum C++ Programming
    Replies: 2
    Last Post: 10-10-2005, 06:25 AM

Tags for this Thread