A complicated situation while using dlsym casting - c

In our code there is a function defined as:
a.h
extern int (*get_prof_action(void))(void);
a.c
static int (*ProfAction)(void) = NULL;
int (*get_prof_action(void))(void)
{
return ProfAction;
}
Then later in main.c, I want to gain this function through dlsym(I have to), so I used like this.
...
int (*p_get_prof_action(void))(void);
...
void my_function(){
...
void *handle=dlopen(mylibrary,RTLD_LAZY);
p_get_prof_action = (int (*(void))(void)) dlsym(handle,"get_prof_action");
...
}
And I got compile error:
error: cast specifies function type at line
(int (*(void))(void)) dlsym(handle,"get_prof_action");
=======================================================
Here are my questions:
This is not my code and I never saw such usage to define a function. Could you let me know what is this?
How do I correctly get this p_get_prof_action?
Thanks very much. This really stucks me a lot!!

You've declared p_get_prof_action as a function, not a function pointer. The correct declaration would be:
int (*(*p_get_prof_action)(void))(void);
And the correct cast would be:
p_get_prof_action = (int (*(*)(void))(void)) dlsym(handle,"get_prof_action")
When dealing with function pointers, a typedef can be very helpful. The function in question is returning a function pointer, so let's make one for the return type:
typedef int (*action)(void);
Then declare your function pointer to return that type:
action (*p_get_prof_action)(void);
And assign to it like this:
p_get_prof_action = (action (*)(void))dlsym(handle,"get_prof_action");

Related

Too few arguments to function while setting a value in an array of pointers to functions

I was trying to create an array of function pointers with the following piece of code:
#include <stdio.h>
int functu(int ,int);
int ghonchu(int,int);
int main()
{
printf("Hello, World!\n");
int (*acrib[10]) (int,int);
acrib[0] = (*functu)(int,int);
return 0;
}
On compiling this program, an error is thrown saying "too few arguments to function 'functu'".
What can be the cause of it? Am I missing anything trivial?
You seem to be confusing & (which returns a pointer) with * (which dereferences a pointer).
You need to change this:
acrib[0] = (*functu)(int,int);
to this:
acrib[0] = &functu;
See: http://ideone.com/r1Xqa6
You should have function implementation, then assign the implementation to the pointer before using it. short example

Call flow for the code - C

I am looking into some C code for a microcontroller. I understand most of the code however this piece of the code is puzzling me.
I am also including relevant definitions for used data types. I have substituted function and variable names for the ease sake.
#define COUNT (2)
typedef void(*some_type)(void *p);
some_type some_arr[COUNT] = {NULL, };
void init(void)
{
first_function(&second_function);
}
void first_function(some_type cb)
{
if(some_arr_count < COUNT)
{
some_arr[some_arr_count++] = cb;
}
}
void second_function(void *p)
{
another_type *req;
req = (another_type *)p;
//some other code goes here
}
1.What does this typedef means?
typedef void(*some_type)(void *p);
init() function gets called only once and it has only one line of code.
2.What does this line do?
first_function(&second_function);
I searched for the term second_function in the entire project code and it this the only place it appears besides function definition.
3.So how does second_function get called?
The following typedef
typedef void(*some_type)(void *p);
will define some_type as a pointer to function of type void ()(void *).
The following statement
first_function(&second_function);
is a function call, &second_function, which is the address of second_function , is the argument to first_function().
The function second_function could be called like this
some_arr[some_arr_count](p);
some_arr[some_arr_count] is a function pointer to second_function, which is assigned in first_function, and p is the argument of second_function, which is a pointer to void.
Firstly, as suggested in the comments you should go read about function pointers. I got this (How do function pointers in C work?) from a Google search.
The above link should help to explain answers to question 1 and 2. For question 3, it is likely that the micro-controller has some built-in mechanism or library function which calls all the function call-backs in some_arr[COUNT], something like the following might work (untested):
for (int i = 0; i < COUNT; ++i)
{
if (some_arr[i] == NULL) break;
(*some_arr[i])(&something_useful);
}
Where something_useful would be some sort of data that the call-back function could use.
If you are able to search the library code for uses of some_arr you might find code to call the second_function (although it will no longer be called second_function).

Cast to function pointer

I have come across the line of code shown below.
I think it may be a cast to a function pointer that returns void and takes a void pointer. Is that correct?
(void (*)(void *))SGENT_1_calc
Yes, it is correct. I find that not very readable, so I suggest declaring the signature of the function to be pointed:
typedef void sigrout_t(void*);
I also have the coding convention that types ending with rout_t are such types for functions signatures. You might name it otherwise, since _t is a suffix reserved by POSIX.
Later on I am casting, perhaps to call it like
((sigrout_t*) SGENT_1_calc) (someptr);
Yes, it is. The function should be looking like this
void func(void*);
But the statement is missing a target, since a cast to nothing is useless. So it should be like
func = (void (*)(void *))SGENT_1_calc;
None of the existing answers show it in direct usage, that is, taking a function pointer and casting it in order to call the function. I was playing with this to show the content of my object as json, accessing both the function and the data through anonymous pointers:
#include <stdio.h>
#include <stdlib.h>
typedef struct box1_s{
int a;
char b[50];
}box1_t;
void box1_t_print(void* ptr){
box1_t* box = (box1_t*)ptr;
printf("{\"a\": %i, \"b\": \"%s\"}", box->a, box->b);
}
int main(){
void* print = (void*)box1_t_print;
box1_t mybox = {3, "Hi folks, it's me!"};
void* ptr = &mybox;
printf("mybox = ");
((void (*)(void*))print)(ptr);
return 0;
}
Output of the program:
mybox = {"a": 3, "b": "Hi folks, it's me!"}
Yes, this is a function pointer cast.
Function pointer casts
To help you with casting functions to pointers, you can define an alias for a function pointer type as follows:
typedef void void_to_void_fct(void*);
You can also define a type for a function that takes and returns values:
typedef int math_operator(int, int);
Later, you can store a function into a function pointer type like this:
void mystery(void* arg) {
// do something nasty with the given argument
};
int add(int a, int b) {
return a + b;
}
void_to_void *ptr1 = mystery;
math_operator *ptr2 = add;
Sometimes, you have a function like print_str :
void print_str(char* str) {
printf("%s", str);
}
and you want to store it in your function pointer that is agnostic to the argument type. You can then use a cast like this:
(void (*)(void *))print_str
or
(void_to_void_fct*)print_str
Why do we use function pointers?
Function pointers allow you to "store a function" inside a variable (indeed, you store the address of the function). This is very convenient when you want to allow some code to have diferent behavior depending on user input.
For exemple, suppose we have some data and some way to decode it. We could have the following structure to keep this information:
typedef char* decoder_type(char*);
struct encoded_data {
char* data;
decoder_type *decoder_fct;
};
char* decoding_function_1(char* data) {
//...
char* decoding_function_2(char* data) {
//...
This allows storing both the data and the function to later use them together to decode the data.

Pointer to a function that takes a pointer to another function as argument

This should be a simple question, but I might not be able to word it correctly or I might be trying to defy the principles of the C language because of my lack of experience with it.
All I want to do is, given a pointer to a function, to wrap it inside another function that takes a pointer to a function as an argument, and make a pointer of the later. Better in code:
void do_nothing_1() {}
void do_nothing_2() {}
void wrapper(void(*f)()) { f(); }
int main() {
// the following will call the function
// but i just want a pointer of whats being called
funcion_pointer_1 = wrapper(do_nothing_1);
funcion_pointer_2 = wrapper(do_nothing_2);
return 0;
}
I apologize beforehand if the question doesn't make any sense, please help me clarify it rather than simply downvote it.
Edit: Given the apparent difficulty to obtain the results desired because of the obscurity of the requirements, I will be a little more specific on what I am looking for.
Inside a struct, I have a pointer to a function:
struct my_struct {
int (* run)(void);
}
What I want to do is to modify that function and that's why I use the wrapper. So, for example, if foo returns void change that to int. Also, run some code before executing foo:
int wrapper(void (*foo)()) {
// exec some stuff here
foo();
return 0;
}
Ultimately, what I want is that when I execute the function corresponding to the *run pointer from my structure, execute some stuff before doing run() and change the return type.
When struggling with the correct syntax, it is helpful to use typedefs to make things clearer. Not just for yourself as you write the code, but for anyone who needs to maintain it, or just try to figure out what it's doing.
You want a function pointer to a function that takes another function pointer as an argument. Start with the argument, a function without parameters and no return value:
typedef void (*void_handler_t)( void);
And now the wrapper function pointer, one that takes a function pointer parameter and has no return value:
typedef void (*wrapper_handler_t)( void_handler void_fn);
And the code:
void foo( void) {}
void wrapper( void_handler_t wrapped_fn)
{
wrapped_fn();
}
int main( int argc, char *argv[])
{
wrapper_handler_t function_pointer;
function_pointer = &wrapper;
function_pointer( &foo);
return 0;
}

c function chaining possible?

I was wondering if it is possible in C (89/90) to chain function calls, and where it is defined in the C spec. I assume this isn't possible since a google search reveals no mention of it.
I thought of this because of a related conversation with a friend of mine where he told me that given a function returning a struct, you cannot perform any operations on said struct within the same statement; instead, you have to assign the result of the function to a variable, and then manipulate the struct via the variable instead of directly from the function result itself. This leads me to believe that you can't chain functions either, but I can't seem to find these limitations discussed in the spec.
Edit : Sorry, I should have been specific on the return value. Assuming the function returns a function pointer, is it possible to dereference and call the result within the same statement, in fluent fashion?
For example, assuming getFunc returns a function pointer :
(*getFunc(getFuncParam))(otherFuncParam)
Or in the struct case, assuming a struct with an int member called count:
funcReturnsStruct(param).count++
Here's what function chaining looks like in C:
post_process(process(pre_process(data)));
Obviously, your friend is wrong. As long as the functions cooperate by accepting and returning the same type of value you can chain the calls all you like.
Contrast this with something like
data.pre_process().process().post_process();
The big difference is that in C (which has no encapsulation, hence no classes) functions have center stage while in more modern OO languages it's objects that get more attention.
Update: Sure it's possible to chain no matter what each function might return. For example:
int increase(int x) {
return x + 1;
}
typedef int (*increase_fp)(int);
increase_fp get_increase() {
return increase;
}
int main(void) {
printf("%d", get_increase()(1));
return 0;
}
See it in action.
a friend of mine where he told me that given a function returning a struct, you cannot perform any operations on said struct within the same statement
Your friend is correct in the sense that the return value of a function cannot be the target of an assignment (it's not an lvalue). IOW, you can't do something like
int foo(void) { int x = 5; return x; }
...
foo() = 6;
However, if the return type of a function is a struct or a union, you can apply the component selection operator to the return value, such as
int x = foo().memb;
Similarly, if the return type of the function is a pointer to a struct or a union, you can write
int x = foo()->memb;
And if the return value is a pointer to another function, you can call that other function like so:
int bar(int x) { ... }
int (*foo)(int x) { return bar; }
int x = foo(x)(y); // or (*foo(x))(y) -- the result of foo(x) is
// called with the argument y
although anyone who has to maintain or debug your code may beat you severely for it.
What you cannot do is something like
foo().memb= ...;
foo()->memb = ...;
which wouldn't make sense anyway, because the lifetime of the value returned by foo ends when the statement ends - you wouldn't be able to retrieve that modified value.
Your friend is wrong.
If we have:
struct Point3
{
float x, y, z;
};
const Point3 * point3_get_origin(void);
then you can certainly do:
printf("the origin's y coordinate is %f\n", point3_get_origin()->y);
The function returns a value of the given type, so the call of the function can be used wherever such a value is needed in an expression.
Do you mean something like this?
typedef void (*CALLBACK)(void);
CALLBACK getCallback();
void test()
{
getCallback()();
}
It compiles with no warning in GCC 4.6.1 (default std).
There's a much faster and easier way to answer this than posting here: try it.
#include <stdio.h>
struct s {
int a;
} s;
struct s * getS() {
s.a = 13;
return &s;
}
int main(int argc, char * const argv[]) {
printf("%d\n", getS()->a);
return 0;
}
% gcc test.c -o test -Wall -pedantic
% ./test
13
%
Not so much as a pedantic warning. Expected output. Looks like it's perfectly fine. However, as has been pointed out, it would be better to store the return value and check for errors.

Resources