Thread: Extract function name as argument[0]?

  1. #1
    Registered User profxtjb's Avatar
    Join Date
    May 2004
    Posts
    8

    Question Extract function name as argument[0]?

    I have been working on a function of functions, e.g., function 'bob' which takes a pointer to a function, uses it and then drops results into an external data structure, viz.

    void bob( float (*generic_function)( float), float b1, struct data data_set );

    void bob( float (*generic_function)( float), float b1, struct data data_set )
    {
    /* bunch of actions using 'generic_function' */
    /* park the results in 'data_set' */
    /* extras */
    }

    What I would like to do in bob, for handling errors, is to get a handle on the name of the specific function passed to 'bob' so that if, for example, it does not converge on a solution, I can write an error message stating so. I want it in the section marked /* extras */

    E.g., with data structure 'dd' and functions 'f1',

    struct data{ ... } dd;
    float (*p_function)( float );
    p_function = f1;
    float f1( float x )
    {
    return x/2.0;
    }

    If I get a non-converging condition in

    bob( p_function, bb1, dd );

    then I would like 'bob' to produce a message like "Function f1 is not converging!" before exiting.

    SO.... how does a person get a hold of that function name, in this case, 'f1' from the pointer to function 'p_function'? My problem is, I do not even know the vocabulary and phraseology to use to search this question in Google etc.

    I was looking at using stdarg.h, getting argument zero from the function parameters list, but the C book I have only covers its use of va_list() etc. for functions with an unspecified number of arguments, and then only from within the function itself. I need the "functionof functions" to get that argument[0].

    Gracias for the assistance!

  2. #2
    Welcome to the real world
    Join Date
    Feb 2004
    Posts
    50
    You could have Bob ( ... ) return an int. As in:

    Code:
    int bob ( your parameters )
    {
         int rVal = -1;
    
        do 
        {
            pseudocode...
            ...
            rVal = a ret val
        } while (false);
    
        return rVal
    }
    Somewhere within the do-while loop rVal will be set to something other than -1, if not, than an error ocurred and you can do what you want with the return value from where you called it from. Just an idea.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >then I would like 'bob' to produce a message like "Function f1 is not converging!" before exiting.

    I'm not sure whether something akin to this may be adaptable to your problem.
    Code:
    #include <stdio.h>
    
    struct sFunction
    {
       void (*call)(void);
       const char *name;
    };
    
    void foo(void) { puts("in foo"); }
    void bar(void) { puts("in bar"); }
    void baz(void) { puts("in baz"); }
    
    void qux(struct sFunction *f)
    {
       printf("calling %s: ", f->name);
       f->call();
    }
    
    #define BIND(x)   {x,#x}
    
    int main()
    {
       struct sFunction table[] =
       {
          BIND(foo),
          BIND(bar),
          BIND(baz),
       };
       size_t i;
       for ( i = 0; i < sizeof table / sizeof *table; ++i )
       {
          qux(&table[i]);
       }
       return 0;
    }
    
    /* my output
    calling foo: in foo
    calling bar: in bar
    calling baz: in baz
    */
    [edit]Maybe this is a little closer approximation.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct sFunction
    {
       float (*call)(float f);
       const char *name;
    };
    
    float foo(float f) { return f / 2.0F; }
    float bar(float f) { return f / 2.0F; }
    float baz(float f) { return f / 2.0F; }
    
    void test(float (*call)(float), const char *name)
    {
       static const char *outcome[] = { "Ok", "Error"};
       int result = call(rand()) < RAND_MAX / 4.0F;
       printf("%s: %s\n", name, outcome[result]);
    }
    
    #define BIND(x)   {x,#x}
    
    int main(void)
    {
       size_t i;
       struct sFunction table[] = { BIND(foo), BIND(bar), BIND(baz) };
       srand(3);
       for ( i = 0; i < sizeof table / sizeof *table; ++i )
       {
          test(table[i].call, table[i].name);
       }
       return 0;
    }
    
    /* my output
    foo: Ok
    bar: Ok
    baz: Error
    */
    [/edit]
    Last edited by Dave_Sinkula; 05-26-2004 at 11:05 AM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User profxtjb's Avatar
    Join Date
    May 2004
    Posts
    8
    Dave, I think something like what you propose could be worked. Basically, you want to set up a table or list of functions.

    However, I want to be able to be a bit more agile.

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    C99 includes a predefined identifier called __func__ that does pretty much what you want. If you have a compiler that supports this feature then you could use that.
    My best code is written with the delete key.

  6. #6
    Registered User profxtjb's Avatar
    Join Date
    May 2004
    Posts
    8
    Quote Originally Posted by Dave_Sinkula
    >then I would like 'bob' to produce a message like "Function f1 is not converging!" before exiting.

    I'm not sure whether something akin to this may be adaptable to your problem.
    Code:
    #include <stdio.h>
    
    struct sFunction
    {
       void (*call)(void);
       const char *name;
    };
    
    void foo(void) { puts("in foo"); }
    void bar(void) { puts("in bar"); }
    void baz(void) { puts("in baz"); }
    
    void qux(struct sFunction *f)
    {
       printf("calling %s: ", f->name);
       f->call();
    }
    
    #define BIND(x)   {x,#x}
    
    int main()
    {
       struct sFunction table[] =
       {
          BIND(foo),
          BIND(bar),
          BIND(baz),
       };
     
    [etc. deleted]
    [edit]Maybe this is a little closer approximation.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct sFunction
    {
       float (*call)(float f);
       const char *name;
    };
    
    
    [etc. deleted]   
    
    
    #define BIND(x)   {x,#x}
    
    int main(void)
    {
       size_t i;
       struct sFunction table[] = { BIND(foo), BIND(bar), BIND(baz) };
    
    [etc. deleted]
    [/edit]
    Dave, yes, these BIND operations might work; I will have to look up BIND.

    BUT, the thing is, that I want to get at the function name itself, on the fly, without having a homemade list of names inside your structure sFunction, as you have proposed in both blurbs above. That is, if I were to include a set of external functions from Timbuktu,

    #include "timbuktu_functions.h"

    and then make a call

    p_function = timbuktu_f23;
    bob( p_function, b1, dd);

    I would like 'bob' to pop the name out without having to manufacture a tiresome list.

    In a way, it is kind of phony, now that I think of it, because somewhere else in 'main' I would have the computer make a selection of one of the timbuktu functions, so I will know the name at that point. I could slap the name into a

    char *function_select[ int ];

    I guess and be done with it, letting 'bob' re-extract the name from 'function_select'.

    However, I want to take apart a function!!!!

  7. #7
    Registered User profxtjb's Avatar
    Join Date
    May 2004
    Posts
    8
    Quote Originally Posted by Prelude
    C99 includes a predefined identifier called __func__ that does pretty much what you want. If you have a compiler that supports this feature then you could use that.
    Yes, that will pop the name out of any function I want. I tried it. OK.

    Code:
    int f1( int  x ){
    printf( "My name is %s.\n", __func__ );
    return x/2.0;
    }
    output
    My name is f1.

    However, how can I get a "function of a function" to do it? I.e., extract the name of a function, given a pointer to it?

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    There is nothing called "BIND" that you can just look up some place. "BIND" is a #define preprocessor macro that Dave made. Basicly what it does is take one argument, then make a string out of whatever you pass it:
    Code:
    #define BIND(x)   {x,#x}
    The use of the # operator here is a "stringization" operator. That is, it takes the text passed to it, and wraps quotes around it, and makes it a string literal. The use of the comma operator makes this macro define both members of the structure. This only works because it was designed to work specificly for that structure. It could work other ways, but this is a specific macro created for this instance. There's nothing really to look up, other than if you want to familiarize yourself with the # token/operator.

    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User profxtjb's Avatar
    Join Date
    May 2004
    Posts
    8
    Quote Originally Posted by quzah
    There is nothing called "BIND" that you can just look up some place. "BIND" is a #define preprocessor macro that
    true
    I figured that out around 2 min after I posted the reply.

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >However, how can I get a "function of a function" to do it? I.e., extract the name of a function, given a pointer to it?
    Either use a buffer passed into the function or return a string from it:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    const char *
    foo(
      char *buf
      )
    {
      /* Option 1 */
      strcpy(buf, __func__);
      /* Option 2 */
      return __func__;
    }
    
    int
    main(void)
    {
      char buf[50];
      const char *(*f)(char *) = foo;
    
      puts((*f)(buf));
      puts(buf);
    
      return 0;
    }
    __func__ can be used as if it were declared static, so returning it is perfectly acceptable. If you can't modify either the return type or the parameters of the function in question then your only other reasonable option is to push the string onto some global error handling data structure for later use.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  2. dllimport function not allowed
    By steve1_rm in forum C++ Programming
    Replies: 5
    Last Post: 03-11-2008, 03:33 AM
  3. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM