In C, how to do you call a function from just having its name as a string? I have this:
int main(int argc, const char *argv[])
{
char* events[] = {
"test",
"test2"
};
int i = 0;
for (; i < 2; ++i){
char* event = events[i];
// call function with name of "event"
}
return 0;
}
You can do it, but there's not much built-in to help out.
typedef struct {
char *event_name;
void (*handler)();
} event_handler;
then search through an array (or whatever) of event_handlers, and when you find the right name, call the associated function.
There is no standard way to do this. In practice you can sometimes do it using platform specific things (such as dlopen on *nix), but it's just not a very good idea. If you really want to do something like this, you should be using a reflective language.
Set up a table of structs of strings and function pointers to use as a lookup for your function.
If you want to call a function that was linked in using the dynamic linker (or if your program was compiled with -rdynamic) you can use dlsym() to get the address of a function pointer and call that.
If you'd like to invoke a function based on the contents of a given string, you can use the above, or you can wrap a constant string with a function pointer inside of a structure and invoke each.
Compare the input string against known function names.
If string X... call function X
since your array only has 2 items... my noob way =)
if ( strcmp(event, "function1") == 0 ) {
function1();
} else if { strcmp(event, "function2") == 0 ) {
function2();
}
Related
Basically I have this data structure:
typedef struct Data {
char *str;
int n;
} TData, *AData;
Where I want to allocate space for str using malloc (in that variable I am putting a string that I read from a file which, honestly, it's not that important considering the topic of my question). Therefore, I created a function TData InitData(const char *file_name):
TData InitData(const char *file_name) {
TData data;
data.str = malloc(1024);
if (!data.str) {
printf("Allocation error!\n");
// I have no idea what to return here in order to exit the function.
return (...);
}
return data;
}
Now, in my 'main()' function, I would make the call something like this:
int main(int argc, const char * argv[]) {
TData data;
if(!(data = ReadExpression(argv[1]))) {
return 1;
}
// I do something with my data and the program ends.
return 0;
}
How can I make the return statement valid in the InitData function?
I know that the other way, and probably the recommended way is either to send TData data from main to InitData as a parameter of type AData and change the type of the function to int (would result into something like: int InitData(const char *file_name, AData data)) or to simply use AData.
As a rule of thumb, always pass structs as pointer parameters and not by value.
As a rule of thumb, when writing complex functions, reserve the return value for errors.
So in your case, rewrite the function as:
bool InitData (TData* data, const char *file_name);
where the bool can be replaced by an enum for more detailed error codes. Right now the function result is only "ok" or "error".
C does not have an inbuilt multiple value return, so usually what you do is
int InitData(const char *file_name, TData *returnedData) { ... }
The return value of InitData is then the error/success flag and the TData structure is returned via the pointer.
i did not do much in C but many functions are like this:
int foo(intargs, outargs);
the thing behind this is that you allocate the object and pass it as a reference to be filled inside the function.
the return value of the function will be an enum or something like this to be compared to determine what happened.
I love the way MicroVirus suggested. Accepting the data as a parameter also be used for multithreaded code safety. Moreover, you can return the result of operation in order to check in the calling code. Your TData is not a pointer so you can not set it to NULL, which is a one way of telling an invalid case I think. However, there is another problem here! TData data in InitData is a local variable and should be copied when the function returns. It is not a good practice for performance issues I think. I suggest, accept the object as a parameter (as a pointer for example) return the result of the function to the calling code and check that for the validity of the data. You can set data NULL or not, but when you return a result value this makes everything cleae without checking the data object itself.
Just return data as normal, but change your code in main() to read:
data = ReadExpression(argv[1]);
if ( !data.str ) {
return 1;
}
You can't return a scalar value in place of a struct, and your question suggests you already know you can use a pointer but are choosing not to, so this is the simplest alternative way.
You could have a flag in the Data-struct set depending on the if (!data.str) result, and always return data.
Then check the flag whenever you want to know what happened.
Just to clarify:
You could write something like this, or similar:
`typedef struct Data
{
char *str;
int n;
char myflag;
const char *file_name;
} TData, *AData;`
`void InitData(TData *data)
{
data.str = malloc(1024);
if (!data.str)
{
printf("Allocation error!\n");
myflag=0;
}
else
{
myflag=1;
}
return data;
}`
But see the comments also. Just wanted to give another perspective.
I have an application where the arguments list cant be reeeealy long. I can run my app like this:
./app -operations a b c d e f g h i j ...
And so on. My a,b,c ... are algorithms which I would like to run (functions defined in my code). To be able to execute them, I have something like this:
if(a)
funA();
if(b)
funB();
if(c)
funC();
...
It does not look nice, does it? I must say, there's much more calls than just 26, since my application grows and grows, my arguments list grows too. I'm looking for a fancy way to make it simpler/prettier. Is it possible, anyone with an idea?
I dont want to use C++ nor external libraries for making it simpler. Can it be done in pure C?
Here is a very simplified possible option:
#include <stdio.h>
// create a common structure to hold all your
// function parameters;
typedef struct Parameters
{
int p1;
int p2;
} Param_Type;
// sample function 1
void func1( Param_Type *params ) {
printf("hi from func1: %d\n", params->p1 );
}
// sample function 2
void func2( Param_Type *params ) {
printf("hi from func2: %d\n", params->p2 );
}
int main() {
Parameters p;
// parse the command line and populate the parameters struct;
p.p1 = 1;
p.p2 = 1;
//create a lookup table with pointers to each function.
void (*F_A[2])(Param_Type *) = {func1, func2};
//You will still need some function, that given a set of arguments, can
// derive and return an index into the array that maps to the correct
/ function.
int func_idx = your_mapping_function(...) // todo
// dispatch the correct function call.
(*F_A[func_idx])(&p);
return 0;
}
You can use use getopt() to read the command line parameters.
And I don't see any optimization in the way you are deciding what action to take depending upon the arguments. I'd say it's just a bad design of doing things. You could try changing your approach.
You could use enums and function pointers to define handlers for every different set of arguments.
Something in the lines of:
typedef enum {
ARG_A,
ARG_B,
ARG_C,
// etcetera
MAX_ARGS
} CmdArgId;
bool cmdArgStates[MAX_ARGS];
typedef void (*CmdHandler_f)();
CmdHandler_f cmdHandlers[MAX_ARGS] = {
// TODO: set function pointers
};
int main()
{
// set cmdArgStates[] indexes to true or false,
// according to the program command line.
ParserCmdArgs();
for (int i = 0; i < MAX_ARGS; ++i)
{
if (cmdArgStates[i] == true)
{
cmdHandlers[i]();
}
}
}
If you need the handler functions to have different numbers of arguments, you can define a common function with a fixed number of args and just ignore them when they are not needed. I.e.: typedef void (*CmdHandler_f)(); could also de something like typedef void (*CmdHandler_f)(int, int, int);
One idea would be to create a structure that can be used to abstract each command line option. Here is a possible method you could use to implement that idea :
Create a structure that can represent each function you need to
support, and have it hold a pointer to the function and a string for the search key.
Create an array of this structure and initialize the members accordingly
Use an algorithm, such as a binary search, to find the key in the structure array when looping through the command line arguments.
Once you have the structure from the key, you can then call the function which will handle the behavior desired in the option.
It's possible this won't apply to your situation, but this really is an implementation specific problem. If you want a more specific solution, you should probably post more details about your functions and the implementation behind them.
I would like to call C functions (e.g. form the stdlib, math ...) dynamically. This means that my C program only knows the pointer to a random function (e.g. printf) and its signature (coded as a char array: char *, ...).
My goal is a reflectCall-function that gets a pointer to a function (&printf), a signature (somehow coded in a char[]), and the parameters as a long[] (long is not the actual datatype, one long value can also represent a double value, pointer,...).
The signature of my reflect function therefore looks like this:
long reflectCall(void *funcPointer, char[] types, long[] args)
The function should do the actual call of the function *funcPointer and finally return its result.
As a result, I can not create a pointer pointer; e.g. like this one:
int (*functionPtr)(int,int);
Can anybody give me a hint how to solve this problem or suggest any reference implementation?
It is possible to do it in pure C but it is not so simple and not so quick:
Create wrapper functions for all functions you want to call, such as:
int WrapPrintf(const char* types,long* args,long* results)
{
// Function specific code, in this case you can call printf for each parameter
while(*types)
{
switch(*types){
case 'i':
printf("%d",(int)*args);
break;
case 'c':
printf("%c",(char)*args);
break;
// .. and so on
}
++types;
++args;
}
// Return number of filled results
return 0;
}
int WrapFoo(const char* types,long* args,long* results)
{
// ..function specific code..
return 0;
}
Pointer to a wrapper function:
typedef int (*TWrapper)(const char*,long*,long*);
Create a table structure for wrapped functions:
struct STableItem{
const char *strName;
TWrapper pFunc;
};
Create a table:
STableItem table[] = {
{"printf", &WrapPrintf},
{"foo", &WrapFoo},
{NULL, NULL}
};
Create interface to call any function from the table (search function by name and call it):
int DynamicCall(const char *func_name,const char* types,long* args,long* results)
{
int k;
for(k=0;table[k].strName != NULL;++k){
if(strcmp(func_name,table[k].strName) == 0){
return table[k].pFunc(types,args,results);
}
}
return -1;
}
And finally make a call:
long args[] = {123,'b'};
long results[8]; // not nice but just for an example
int res_count = DynamicCall("printf","ic",(long*)args,(long*)results);
Note: use a hash function for quicker name search
C does not provide the facilities to do this. You'd have to write the body of the function in platform-specific ASM.
I would to recommend you to look at libffi, whether it fits your needs...
http://sourceware.org/libffi/
http://en.wikipedia.org/wiki/Libffi
As explained elsewhere, there is no way to do this truly dynamically. However, if you wish to build a table of functions using pointers, and use some sort of string or index to describe what you want to do, then that would certainly be possible, in a portable way. This is not at all uncommon as a solution for various parsing and other "run code based on commands, etc".
But it does require that you use a function pointer of some sort [or cast your void * into one at some point or another]. There is no other (even nearly) portable way of calling a function dynamically in C.
can any one explain the following instructions:
int *c[10];
char *(**n)(void);
float *(**r(void))[6];
short *(**v(void))(int);
long *(*(*(*z)(void))[7])(void);
http://www.cdecl.org/ will explain all these statements. C Right-Left rule explains how to read C declerations pretty well. There are plenty of other resources available, notably in this question.
Since this is your homework you won't learn this by me telling you everything ;) But, one hint. You can create and pass pointers to functions in C, not just variables.
Function arguments of all but the first example are prototypes for function pointers.
Say we have a library for testing colours, we might want to allow the users of our library to provide custom ways of getting the name of the colour. We might define a struct for users to pass in containing callbacks we can call.
struct colour_tester {
char *(*colour_callback)(void);
}
// test the user's function if given
void run_test(struct colour_tester *foo ){
// use the callback function if set
if ( foo->colour_callback != NULL ){
char * colour = (*foo->colour_callback)();
printf( "colour callback returned %s\n", colour );
}
}
Users of the library would then be free to define implementations of these callback functions and pass them to us as a function pointer.
#include <colour_tester.h>
char * get_shape_colour(){
return "red";
}
int main ( int argc, char** argv ) {
// create a colour tester and tell it how to get the colour
struct colour_tester foo;
foo.colour_callback = &get_shape_colour;
run_test( &foo );
}
I've leave you to work out what is going on with the ones with extra numbers of *s.
I wonder if it's possible to do something like:
call("MyFunction");
and have it call a function named MyFunction not having call implement a long switch or if statement.
there probly is some other way to do this, what I really want to achive is to implement the IRC protocol, which get messages, and based on those I want to call the apropiate function
I'm new to C and best practices how things are done so please enlighten me!
Not without defining a table of string-to-function mappings and (probably) some kind of argument passing convention, or using dlopen() (which counts as very advanced hackery).
Not out of the box with C. You could have a hash map or dictionary that has the string as a key and a function pointer. You look up in your dictionary using the string key, then call the function pointer.
There is no way to directly call a function by string like you want in the standard C library. If it were C++, you could create a std::map of string to function pointer, but not in C. You'll probably have to resort to a series of strcmps if C++ is not an option.
/* These are your handler functions */
void user_fn() { printf("USER fn\n"); }
void pass_fn() { printf("PASS fn\n"); }
/* Stores a C string together with a function pointer */
typedef struct fn_table_entry {
char *name;
void (*fn)();
} fn_table_entry_t;
/* These are the functions to call for each command */
fn_table_entry_t fn_table[] = {{"USER", user_fn}, {"PASS", pass_fn}};
/* fn_lookup is a function that returns the pointer to the function for the given name.
Returns NULL if the function is not found or if the name is NULL. */
void (*fn_lookup(const char *fn_name))() {
int i;
if (!fn_name) {
return NULL;
}
for (i = 0; i < sizeof(fn_table)/sizeof(fn_table[0]); ++i) {
if (!strcmp(fn_name, fn_table[i].name)) {
return fn_table[i].fn;
}
}
return NULL;
}
int main() {
fn_lookup("USER")();
fn_lookup("PASS")();
}
You make a table which relates each string to a function pointer. You then look up the string in the table, and invoke the function through the pointer. The classic K&R text includes code something like this.
I am not a C programmer, and personally would do IRC stuff in a dynamic language, but you could do the following:
create a struct with string field and a function pointer, make an array of all your functions with their "string", sorted by the string. On call, do a binary search on the array, by string, and call the function pointer in the found struct.