Products > Programming

GCC ARM32 compiler too clever, or not clever enough?

<< < (20/20)

Nominal Animal:
I occasionally use an array of structures containing the name, optionally a type identifier, and a function pointer:

--- Code: ---enum {
    FUNCTYPE_NONE = 0,
    FUNCTYPE_FLOAT_UNARY,  /* Returns a float, takes one float as an argument */
    FUNCTYPE_FLOAT_BINARY, /* Returns a float, takes two floats as arguments */
};

typedef struct {
    const char  *name;
    int    type;
    union {
        float (*float_unary)(float);          /* .type = FUNCTYPE_FLOAT_UNARY */
        float (*float_binary)(float, float);  /* .type = FUNCTYPE_FLOAT_BINARY */
    };
} function_descriptor;

const function_descriptor  func[] =
{
    { .name = "sin", .type = FUNCTYPE_FLOAT_UNARY, .float_unary = sinf },
    /* Other functions omitted */
    { .name = NULL, .type = FUNCTYPE_NONE }
};
#define  funcs  ((sizeof func / sizeof func[0]) - 1)

--- End code ---
Valid indexes are 0 through funcs-1, inclusive; or you can loop until .name==NULL or .type==FUNCTYPE_NONE.

This is useful when one needs to execute a function when given its name as a string:

--- Code: ---int  exec_float_unary(const char *name, float *result, float arg);
int  exec_float_binary(const char *name, float *result, float leftarg, float rightarg);

--- End code ---
where the return value is 0 if successful and nonzero for error codes, result points to where the result is stored, and arg, leftarg, and rightarg are arguments passed to the function.

(It is pretty obvious that the most recent case I used this at was a calculator/expression evaluator...)

In case of an extensible calculator/expression evaluator -type thingy on a fully featured OS, I like to use

--- Code: ---static size_t               funcs_max = 0;
static size_t               funcs = 0;
static function_descriptor *func = NULL;

int register_float_unary(const char *name, float (*func)(float));
int register_float_binary(const char *name, float (*func)(float, float));

--- End code ---
so that plugins can provide new functions ELF-magically using

--- Code: ---__attribute__ ((__constructor__))
static void register_functions(void)
{
    register_float_unary("sin", sinf);
    register_float_unary("cos", cosf);
    register_float_unary("tan", tanf);
    register_float_binary("atan2", atan2f);
}

--- End code ---
where the constructor function attribute causes the linker to add the address of that function into an ELF section, so that either the startup code (if static) or dynamic linker (if dynamic) will execute it when the ELF object is loaded.

Navigation

[0] Message Index

[*] Previous page

There was an error while thanking
Thanking...
Go to full version