I have an array of structs. The struct has two function pointers. Each element of the array needs the function pointers to point to different functions, so that the function corresponding to a particular element can be called without knowing the specific function name. Being new to function pointers, it seems to me that what I’m doing is not going to work, but I’m not sure how to do it correctly. An example of how to call one of the functions being pointed to would also be appreciated.
Here are the prototypes of the functions I’m trying to reference:
int edit_translate_concise(struct ged *gedp, const union edit_cmd * const cmd);
int edit_translate_add_arg(union edit_cmd * const cmd, struct edit_arg * const arg);
The struct and the array of that struct are as follows:
struct edit_cmd_tab {
char *name;
char *opt_global;
char *usage;
char *help;
int (*exec_concise)(struct ged *gedp, const union edit_cmd *const cmd);
int (*add_arg)(union edit_cmd *const cmd, struct edit_arg *const arg);
};
static const struct edit_cmd_tab edit_cmds[] = {
...
{"translate", (char *)NULL,
"[FROM] TO OBJECT ...",
"[[-n] -k {FROM_OBJECT | FROM_POS}]\n"
"[-n] [-a | -r] {TO_OBJECT | TO_POS} OBJECT ...",
&edit_translate_concise,
&edit_translate_add_arg
},
...
};
So, the functions I need to point to take the same arguments and return the same type as the function pointer members of the struct.
I’m getting these warnings, referring to the last two lines of the first struct:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:867:54: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
And these warnings referring to the last two lines of the array:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: (near initialization for ‘edit_cmds[1].exec_concise’) [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: (near initialization for ‘edit_cmds[1].add_arg’) [enabled by default]
You are doing [almost] everything correctly.
However, you have to make sure that the actual union
union edit_cmdis declared before you use it in function prototype. If you forget to declare it, the compiler will treatunion edit_cmdas a declaration of a completely new union type, which is local to function prototype. I.e. this local declaration ofunion edit_cmdwill have no relation to the actual declaration of yourunion edit_cmdyou’ll have elsewhere.This is what happens in your case. This is what the compiler is trying to warn you about. The same applies to
struct gedand tostruct edit_arg. Apparently, you forgot to include the header files that contain declarations ofunion edit_cmd,struct gedandstruct edit_arg.For example, this simple code illustrates the problem
the
union bardeclared in thefoo‘s prototype has absolutely no relation tounion bardeclared later. The former is local to the prototype, the latter is global (i.e. file-level type). If you later try to doyou’ll get a diagnostic message from the compiler about argument-parameter type mismatch. The very same mismatch is what causing the second group of warnings in your post (about incompatible pointer types in array initialization).
But if you rearrange the declarations in this way
everything will work fine, since
union barin the prototype now refers to previously declaredunion bar. Alternatively, you can forward-declareunion baras inThis will also make the compiler treat
union barinfooas a global type (i.e. file-level type), not as a local one.As for calling your functions through the pointers, it can be done as either
or even without the
*operatorTo summarize the above, the easy fix to the problems you are observing is to add the file-level forward declarations for the
structanduniontype before the function prototypesA more elegant approach would be to include the full definitions of these types before the prototype declarations.