Run function from structure variable - c

I try to run a function with a structure, because I work with a module who send callback so I want to execute the fuction to anwser to the callback.
typedef void (*bgs2_e_rx_callback)(unsigned char reason, unsigned short int n, char * data);
void bgs_callbacktest(char* data);
/*void test(int* ptest);
void test_tab(char* data,char* ptaille);
char* concat(const char *s1, const char *s2);
static void parse_numeric_rsp(char nb_values, char * data, unsigned long data_len,unsigned long * result);*/
struct teststruct{
short int i ;
bgs2_e_rx_callback callback;
void* param;
};
struct teststruct leteststruct ;
int main(){
printf("test for function in structure\n");
char txt[]="i'm a text";
leteststruct.param = txt;
leteststruct.callback = &bgs_callbacktest;
}
void bgs_callbacktest(char* data){
printf("your text: %s\n",leteststruct.param);
}
Compilation works good, but I don't see the message of the callback function.

You never call it! Edit your main like this:
int main(){
printf("test for function in structure\n");
char txt[]="i'm a text";
leteststruct.param = txt;
leteststruct.callback = bgs_callbacktest;
// Change the dummy parameters below with yours
leteststruct.callback(0x7f, 512, txt);
}
Then you will have it.

Related

Function pointer pointing to functions with different number of arguments

How to handle assignment of the functions to one function pointer, each with different number of parameters ? The problem is that parameters differ in number and type. If possible give an example.
Function pointers can be cast in the same way as the other pointers. You will have a generic function pointer (similar to void * for storage types), and use it to hold/pass the address of the function. Before calling the function, you will need to cast it to the correct type.
Here is a working example:
#include <stdio.h>
typedef void (*generic_t)(void);
typedef int (*type2_t)(int);
typedef int (*type3_t)(int, char *s);
void test1(void) {
printf("Test 1\n");
}
int test2(int i) {
printf("Test 2 %i\n",i);
return i;
}
int test3(int i, char *s) {
printf("Test 3 %i, %s\n", i, s);
return i++;
}
int main(void) {
generic_t f1, f2, f3;
f1 = &test1;
f2 = (generic_t)&test2;
f3 = (generic_t)&test3;
f1();
int i = ((type2_t)f2)(10);
i = ((type3_t)f3)(20,"This is test");
}
In addition, you will need to implement a mechanism to recognize what is the type of function that the pointer is pointing to. One approach is to use a struct that holds the pointer and the enum of the type.
Another possibility is to create a union of different function pointer types:
union funptr {
void (*v)();
void (*vi)(int);
void (*vs)(char *);
int (*i)();
int (*ii)(int);
int (*iii)(int, int);
int (*is)(char *);
};
You can use void pointers to pass reference to the in and out parameters. Multiple parameters and return values you can wrap in the structs. The return value may return status.
Sometimes it used in low-level device drivers.
typedef int func(void *, void *);
func *fptr;
struct s1
{
int i;
char *s;
};
int test1(void *in, void *out)
{
printf("Test 1\n");
return 0;
}
int test2(void *in, void *out)
{
int *i = in;
printf("Test 2 %i\n", *i);
return *i;
}
int test3(void *in, void *out)
{
struct s1 *s = in;
printf("Test 3 %i, %s\n", s -> i, s -> s);
return ++s -> i;
}
int main(void)
{
fptr = test1;
fptr(NULL, NULL);
fptr = test2;
fptr((int[]){10}, NULL);
fptr = test3;
printf("Returned value: %d\n", fptr(&(struct s1){20,"This is test"}, NULL));
}
You have to declare a new function pointer type for every different signature that you need to handle.

Pass String array and indexes using Struct to a thread in C

I am trying to pass a string array and indexes from where to start end searching in the array, I am unable to solve it from the last two days. I am sending to the pthread_create a struct data thread_data, here i am able to send the int and long data, but not the string array, can someone help me, how to pass these.
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
char * str;
};
struct data thread_data[NUM_THREADS];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
char * str[3];
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
.....
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
...
char work[]={"First Line","Second line","Third line"};
...
while(fgets(arr[index],120, fp)!=NULL){
index=index+1;
thread_data[index].tid=index;
thread_data[index].str=work;
...
rc=pthread_create(&threads[index],NULL,searchString,(void *)&thread_data[index]);
...
}
pthread_exit(NULL);
}
To hold the multiple strings you need 2D array.
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
You need to use pointer to pointer in struct data to hold the above array.
struct data{
.....
const char **str;
size_t lenOfStr;
};
And pass the length of array explicitly to thread function from main function.
Your sample code may look like below.
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct data{
int tid;
unsigned long start;
unsigned long end;
char * word;
const char **str;
size_t lenOfStr;
};
struct data thread_data[3];
void *searchString(void *passeddata)
{
struct data *t_data;
int tid1;
const char **str = NULL;
t_data=(struct data *) passeddata;
tid1=t_data->tid;
str=t_data->str;
int i = 0;
for (i = 0;i<t_data->lenOfStr;i++)
printf("%s\n", str[i]);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
const char *work[]={"First Line","Second line","Third line", "Fourth Line"};
int index = 0;
pthread_t threadid=0;
thread_data[index].tid=index;
thread_data[index].str=work;
thread_data[index].lenOfStr = sizeof(work)/sizeof(*work); // Calculate the size of work here
int rc=pthread_create(&threadid,NULL,searchString,&thread_data[index]);
pthread_exit(NULL);
}

Passing an argument to function pointer

I just can't figure out how to pass an Argument like in the following scenario:
#include<stdio.h>
void quit(const char*);
int main(void){
const char *exit = "GoodBye";
void (*fptr)(const char*) = quit;
(*fptr)(exit);
return 0;
}
void quit(const char *s){
printf("\n\t%s\n",s);
}
This is how my program should work and it does, but when I make a text menu i just can't figure out how to do it:
#include<stdio.h>
#include<stdlib.h>
int update(void);
int upgrade(void);
int quit(void);
void show(const char *question, const char **options, int (**actions)(void), int length);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])(void) = {update,upgrade,quit};
show(question,options,actions,3);
return 0;
}
int update(void){
printf("\n\tUpdating...\n");
return 1;
}
int upgrade(void){
printf("\n\tUpgrade...\n");
return 1;
}
int quit(void){
printf("\n\tQuit...\n");
return 0;
}
void show(const char *question, const char **options, int (**actions)(void), int length){
int choose = 0, repeat = 1;
int (*act)(void);
do{
printf("\n\t %s \n",question);
for(int i=0;i<length;i++){
printf("%d. %s\n",(i+1),options[i]);
}
printf("\nPlease choose an Option: ");
if((scanf("%d",&choose)) != 1){
printf("Error\n");
}
act = actions[choose-1];
repeat = act();
if(act==0){
repeat = 0;
}
}while(repeat == 1);
}
Here I need to change the quit function (int quit(void); to int quit(char *s){};) like in the First example and call it with an argument like const char *exit = "GoodBye"; ==>> (*fptr)(exit);
I know that at this point my program takes only void as argument, but I done it only to illustrate the problem.
I'm very confused about this.
EDIT:
this int (*actions[3])(void) I think is an Array of Function pointers and all 3 function pointers takes void as argument, but I need to know if i can use one pointer to take an argument or i have to re-code the whole program.
Since you have an array of function pointers, all the functions need to be of the same type. So at the very least each function should take a const char * (not all functions need to use it) and the array type should be changed to match.
If you want something more flexible, you can have the functions accept a single void * so each function can be passed a different parameter which it then casts to the appropriate type. This is how pthreads passes parameters to functions which start a new thread. You will lose some compile-time type checking with this, so be careful if you go this route.
EDIT:
An example of the latter:
#include<stdio.h>
#include<stdlib.h>
int update(void *);
int upgrade(void *);
int quit(void *);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])(void *) = {update,upgrade,quit};
show(question,options,actions,3);
return 0;
}
int update(void *unused){
printf("\n\tUpdating...\n");
return 1;
}
int upgrade(void *unused){
printf("\n\tUpgrade...\n");
return 1;
}
int quit(void *message){
printf("\n\tQuit...%s\n", (char *)message);
return 0;
}
void show(const char *question, const char **options, int (**actions)(void *), int length){
...
if (act == quit) {
repeat = act("GoodBye");
} else {
repeat = act(NULL);
}
...
}
Since you are using a an array of function pointers, you don't know which ones to take which arguments. But have You can avoid re-coding it by making the functions to take "unspecified number of arguments". i.e. Remove the void from as the parameter from function definitions and prototypes from of the function pointers and from the quit() function.
int quit(const char*);
void show(const char *question, const char **options, int (**actions)(), int length);
int main(void){
const char *question = "Choose Menu\n";
const char *options[3] = {"Update", "Upgrade", "Quit"};
int (*actions[3])() = {update,upgrade,quit};
...
}
int quit(const char *msg){
printf("\n\tQuit...%s\n", msg);
return 0;
}
void show(const char *question, const char **options, int (**actions)(), int length){
....
int (*act)();
....
}
This works because C allows a function with no explicit parameters to take "unspecified number of arguments". Otherwise, you need to make all functions have similar signatures.

Why updated structure variable not printing

This is my code in which if student marks is greater than 85,scholarship status will be changed to sanctioned, but after updating it is not printing
#include<stdio.h>
#include<string.h>
struct scholor
{
char name[25];
int sem;
int marks;
char status;
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",&s1.name,&s1.sem,&s1.marks,&s1.status);
sanction(s1.marks,&s1.status);
printf("%s",s1.status);
}
status is a single char but you are storing a string into it, effectively doing out of bounds access (undefined behaviour). Change it to an array and then you'll be able to copy.
struct scholor
{
char name[25];
int sem;
int marks;
char status[128];
};
and adjust the calls and passing (since status is an array now -- its name gets converted into a pointer t its first element when passed to functions):
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
Other suggestions:
1. Use a standard prototype for main such as: int main(void)
2. You could usr strcpy to copy the string as opposed to doing it yourself.
Your struct should have status as a character array not a character .Moreover when you scanf an array dont write & before because the name itself points to the assdress of the first element.Your corrected program is :
struct scholor
{
char name[25];
int sem;
int marks;
char status[16];
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
}

Why do I see redefinition error in C?

Following is my code, I am trying to run it in Visual Studio.
#include <stdio.h>
#include <conio.h>
int main()
{
//int i;
//char j = 'g',k= 'c';
struct book
{
char name[10];
char author[10];
int callno;
};
struct book b1 = {"Basic", "there", 550};
display ("Basic", "Basic", 550);
printf("Press any key to coninute..");
getch();
return 0;
}
void display(char *s, char *t, int n)
{
printf("%s %s %d \n", s, t, n);
}
It gives an error of redefinition on the line where opening brace of function is typed.
You call display before declaring it, and in such cases the compiler assumes the return type is int, but your return type is void.
Declare the function before using it:
void display(char *s, char *t, int n);
int main() {
// ...
Also note, that you declare it as receiving char*, but pass string literals to it (const char*) either change the declaration, or change the arguments, e.g:
void display(const char *s, const char *t, int n);
int main()
{
// snip
display ("Basic", "Basic", 550);
//snap
}
void display(const char *s, const char *t, int n)
{
printf("%s %s %d \n", s, t, n);
}

Resources