might be it's silly question but not getting what is wrong in my code.
I am writing simple command parser in which it will initialize appropriate parameters and call appropriate functions related to command code.
Ex.
char buffer[]="1123,13,46";
In above line 1123 is command code and rest of two tokens are parameters. In parser it will first find command code form command table and if command found then it will initialize structure of that command with above parameters.
Currently in my code i am successfully fetching correct command from command table and call that command's functions but failed to initialize the parameters with above values (13 and 46 here).Always getting 0.
As per below code same thing i want in my command parser but little modification
typedef struct
{
void *fields[2];
}tmpStruct;
typedef struct
{
int x;
int y;
}myStruct;
tmpStruct tmp_struct;
myStruct *getParams(tmpStruct *t_struct)
{
myStruct *genericStruct = malloc(sizeof(myStruct));
//setup the order of the fields in the handler
t_struct->fields[0]=(void*)&genericStruct->x;
t_struct->fields[1]=(void*)&genericStruct->y;
return genericStruct;
}
void *fillValue(tmpStruct *t_struct)
{
void *genericStruct;
genericStruct = getParams(t_struct);
*((int*)t_struct->fields[0])=12;
*((int*)t_struct->fields[1])=13;
return genericStruct;
}
void pritValue(myStruct *my_struct)
{
printf("%d %d\n",my_struct->x,my_struct->y);
}
int main()
{
void *genericStruct;
genericStruct = fillValue(&tmp_struct);
pritValue(genericStruct);
return 0;
}
Please find my working source file here
And header file here
The problem is that you are casting function pointers to types of functions that take different parameter types. Trying to make calls to functions through pointers like that is undefined behavior. Although you could potentially get away with calls that are similar - say, return myStruct* in place of void* pointer (although it's still undefined behavior), there is no way you could cast a function that takes an int and a myStruct* to a function type that takes an int and a variable list of arguments.
Changing your functions to the correct signatures to match cmdTableStruct table fixes this problem:
void *setParams(paramHandler_type *pHandler);
int printParams(int commandType,... );
static cmdTableStruct cmdTable[]=
{
{ 1123,setParams,printParams },
//more command in same manner
};
Demo.
Of course now you need to handle parameters from the ... list individually using the functionality from the <stdarg.h> header.
Also, the way you dereference param handler when assigning values is incorrect - the index should be applied to paramValue, not to pHandler:
*((int*)pHandler->paramValue[j]) = (int)atoi(token);
Related
Let's say I have the following I'm using to call a function:
Item dummy;
while (!QueueIsEmpty(pq))
DeQueue(pq, &dummy);
Is there a way to put the dummy parameter into the call itself? Something like:
while (!QueueIsEmpty(pq))
DeQueue(pq, &(Item)NULL);
It looks like the method dequeues an object and copies its value to the dummy variable. Where would you expect it to be copied without providing a place to copy it to?
Do you want to just throw it away and clear the queue this way?
If so I would expect that you have to pass it inside unless there is another method that just clears the queue without even copying it. Maybe some clear method.
This isn't valid C [AFAICT]
From my top comment, you might mean: DeQueue(pq,(Item *) NULL) or simply: DeQueue(pq, NULL)?
You're trying to create a compound literal, but it's being initialized from a [NULL] pointer.
Here's the test program I created:
#include <stdio.h>
typedef struct {
int x;
} Queue;
typedef struct {
int y;
int z;
} Item;
int
QueueIsEmpty(Queue * pq)
{
return 0;
}
void
DeQueue(Queue * pq, Item * item)
{
}
int
main(void)
{
Item dummy;
Queue *pq = NULL;
while (!QueueIsEmpty(pq))
DeQueue(pq, &dummy);
// Is there a way to put the dummy parameter into the call itself?
// Something like:
while (!QueueIsEmpty(pq))
DeQueue(pq, &(Item) NULL);
return 0;
}
Here's the output of gcc:
x.c:38:3: error: conversion to non-scalar type requested
Here's the output of clang:
x.c:38:16: error: used type 'Item' where arithmetic or pointer type is required
What you may have wanted is:
DeQueue(pq, &(Item) { 0 })
But, passing that is a bit of [too much] trickery.
Personally, I've never done something like that. I've always just passed down a NULL pointer.
If you do really want a "dummy" parameter, I'd do the Item dummy; thing [vs the compound literal]. It's actually faster because you don't add the overhead of the initialization.
To me, the compound literal is getting "too cute"
If the function requires the address of a valid object, you can pass in the address of a compound literal:
DeQueue(pq, &((Item){0}) );
I have been struggling with function pointers for some time now. Maybe you guys can help me out.
In my project I have multiple functionalities for the same device and each functionality is written in its own .c file. The generic functionalities (which apply to all device functions) are written in generic.c.
I would like to create a function pointer array in the generic c file and fill that array in the other function files. So I can call the right function based on a device function identifier in the generic file.
What I have right now:
// in generic.h:
typedef void (*func_ptr_t[])(arguments);
extern func_ptr_t devFunctions[3];
And I would like to:
// in function1.c:
#include "generic.h"
devFunctions[1] = &functionName;
But then it complains about a type specifier missing AND the array initializer must be a list. If I add the type like
func_ptr_t devFunctions[1] = &functionName;
I get an error about an incomplete element type 'func_ptr_t'.
I can't initialize the entire array list from one file since it is filled from multiple files.
Anybody got an idea on how to tackle this?
Thanks!
-edit-
Because you can't use statements outside of functions I've changed my application. Now it does not use an array anymore and it updates the function pointer in the generic.c upon calling the specific function file.
So the end result:
In generic.h:
typedef void (*func_ptr_t)(<function arguments>)
In generic.c:
func_ptr_t devFunction;
In function1.c:
#include "generic.h"
extern func_ptr_t devFunction;
void functionToBeCalledFromMain( void ){
devFunction = functionName;
}
void functionName (void ){
// Function to be called from generic.c via function pointer
}
As most of you pointed out, filling the array is a statement which can't be put outside a function (duh...). So what I wanted is not really going to work in this case. I rewritten my application to update a function pointer (not an array anymore) on every run with the function I need. Saves a lot of trouble :)
Thanks guys!
For an example about functions of the type int f(int);, you can check :
/* function definition */
int functionName(int arg)
{
/* do things */
return arg * 2;
}
/* create the type "function pointer int->int" */
typedef int (*func_ptr_t)(int);
/* create the array */
func_ptr_t devFunctions[3];
int main(void)
{
/* associate the good function */
devFunctions[0] = &functionName;
/* call it with an arg */
return devFunctions[0](42);
}
Putting the above comments together, you probably wanted
typedef void (*func_ptr_t)(arg_type_list);
This is my typedef struct
//command look up table structure
typedef struct
{
int commandCode;
int (*process_command) (...);
}cmdTableStruct;
Using int (*process_command) (...); i need to call appropriate function which i have assign to that if command code match.
ex.
static cmdTableStruct cmdTable[]=
{
{ 1123,testFunc},
// more command in same manner
};
here it will call testFunc function if command code 1123 and argument of this function only one. Same it will call different functions but the argument type is different and argument is one.
Now using int (*process_command) (...); in stuct definition it give me error like
Error: #xx: expected a type specifier
I can resolve this error by adding one known type argument
like
int (*process_command) (int x,...);
But i don't want additional argument, i just want it will take one argument and call function with appropriate data type of argument.
is any suggestions?
Posting my comment as an answer, u can consider this:
typedef struct
{
int commandCode;
int (*process_command) (void *ptr);
}cmdTableStruct;
Make the argument to process_command to void *. Pass address of variable of whatever types you need for any specific case. Within each function, typecast to expected, copy to local variables of expected types and use.
Here I provide the concrete example nevertheless. I have a typedef (from a header file maplec.h defining OpenMaple).
typedef struct {
void (M_DECL *textCallBack) ( void *data, int tag, char *output );
void (M_DECL *errorCallBack) ( void *data, M_INT offset, char *msg );
...
} MCallBackVectorDesc, *MCallBackVector;
In my code I want to assign the callback functions to use. In the examples from the manual (http://www.maplesoft.com/applications/view.aspx?SID=4383&view=html) this is done with
MCallBackVectorDesc cb = { textCallBack,
0, /* errorCallBack not used */
...
};
However I want to keep a reference to this variable cb in a structure which I defined as
struct open_maple {
MCallBackVectorDesc *call_back_vector;
};
Then I initialize with
open_maple->call_back_vector = (MCallBackVectorDesc *)malloc((size_t)sizeof(MCallBackVectorDesc));
(open_maple->call_back_vector)->textCallBack = &textCallBack;
(open_maple->call_back_vector)->errorCallBack = 0;
This code does not produce any compiler warnings nor Segfaults, but I do not seem to receive any calls of textCallBack either, while the online example version would work. I tried other definitions and assignments, but always got warnings or Segfaults.
It boils down to the question: How do I correctly assign the pointers to the callback functions collected in the typedef struct if I do not want to assign them at initialization (in the declaration of the variable cb)?
Edit 1
It has been suggested below that the error occurs because I am referencing the textCallBack function as &textCallBack function which generates a pointer from a pointer. However the example works neither with nor without the &. Note also that the following code works:
/* some standard libraries */
#include <stdlib.h>
#include <stdio.h>
void function(void){
printf("IAMHERE\n");
};
int main()
{
void (*myfunction)(void) = &function;
myfunction();
return 0;
}
I am using gcc -o test test.c to compile it.
Edit 2
Some more investigations showed that the problem is supposedly related to my use of OpenMaple.
textCallBack is defined as a pointer to function.
You're taking the address of it -- pointer to pointer to function.
Is that really what you intend to store into your structure?
I am making a reliable data transfer protocol and have the function prototype
void tolayer5(int, char data[]);
With the structs
struct msg {
char data[20];
};
struct pkt {
int seqnum;
int acknum;
int checksum;
char payload[20];
};
And when I call the function in this format:
tolayer5(A, packet.payload);
Where A is an int and packet.payload is a struct pkt, I get the error "undefined reference to 'tolayer5(int, char*)'. Can you help me see what I'm missing here?
void tolayer5(int AorB, char data[])
{
int i;
if (TRACE>2)
{
printf("TOLAYER5: data received:");
for (i=0; i<20; i++)
printf("%c",data[i]);
printf("\n");
}
}
Thank you all for helping with the original issue! :) When trying to fix that one, however, I ran into an infinite loop that I think has something to do with me addressing characters in an array incorrectly (it's been awhile since I've done C like this. Can you help me to find where I'm creating an infinite loop?
I have updated the above code to what I'm now working with. Notice the main changes have been to my function:
void tolayer5(int AorB, char data[])
And this line inside the function: printf("%c",msgReceived.data[i]); since now it's just:
printf("%c",data[i]);
seems you need to link with the obj file that implements tolayer5()
Update:
your function declaration doesn't match the implementation:
void tolayer5(int AorB, struct msg msgReceived)
void tolayer5(int, char data[])
So compiler would treat them as two different functions (you are using c++). and it cannot find the implementation for the one you called in main().
Make sure your declare the tolayer5 function as a prototype, or define the full function definition, earlier in the file where you use it.
As stated by a few others, this is a linking error. The section of code where this function is being called doesn't know what this function is. It either needs to be declared in a header file an defined in its own source file, or defined or declared in the same source file, above where it's being called.
Edit: In older versions of C, C89/C90, function declarations weren't actually required. So, you could just add the definition anywhere in the file in which you're using the function, even after the call and the compiler would infer the declaration. For example,
int main()
{
int a = func();
}
int func()
{
return 1;
}
However, this isn't good practice today and most languages, C++ for example, won't allow it. One way to get away with defining the function in the same source file in which you're using it, is to declare it at the beginning of the file. So, the previous example would look like this instead.
int func();
int main()
{
int a = func();
}
int func()
{
return 1;
}