I've following declarations:
typedef void (*foo)(int op, int arg1, int arg2);
void goo(foo f);
{
BODY;
}
and I want to store function f passed to goo in my code but the natural way of modifying body and adding global foo variable (I cannot change definition of goo but I'm able to edit body):
foo _f;
void goo(foo f);
{
_f = f;
}
is making segfaults. I'd be grateful for any hints.
edit
Based on your full code, you should change the name of your function callback() in test.c to something other than "callback" as you already defined the symbol in pagesim.c. I made this edit and the program ran fine.
Here is a test that compiles and runs, maybe you can spot your error based on this:
#include <stdio.h>
typedef void (*foo)(int op, int arg1, int arg2);
foo _f;
void goo(foo f)
{
_f = f;
_f(1, 2, 3);
}
void testfxn(int op, int arg1, int arg2) {
printf("%d %d %d", op, arg1, arg2);
}
void main() {
goo(testfxn);
}
From the code you pasted, where is you actual function definition of type
void func(int op, int arg1, int arg2)
The segment fault is from goo(), you see output from printf(), but the following call of callback2() generate segment fault. callback2 is a function pointer, but it doesn't point to any actual function.
you should define a function
void func(int op, int arg1, int arg2)
{
printf("%d %d %d\n", op, arg1, arg2);
}
then you call goo() and page_sim_init() as
goo(func);
page_sim_init(page_size, mem_size, addr_space_size,
strategy, max_concurrent_operations, func);
Related
I want to forward args of variadic function, I have already find the some topic.
Forward an invocation of a variadic function in C
When I start to practice, I found a problem.
#include <stdio.h>
#include <stdarg.h>
void fun1(const char *msg, ...) // try to forward printf
{
va_list arg_list;
va_start(arg_list, msg);
vprintf(msg, arg_list);
va_end(arg_list);
}
void fun2(const char *msg, ...) // try to forward fun1
{
va_list arg_list;
va_start(arg_list, msg);
fun1(msg, arg_list);
va_end(arg_list);
}
int main()
{
fun1("this is int %d, float %f\n", 1, 2.3);
fun2("this is int %d, float %f\n", 1, 2.3);
return 0;
}
I compile code with gcc main.c and the output shown that
this is int 1, float 2.300000
this is int 6684168, float 2.300000
I can not understand why the fun2 not forward the args of fun1 correctly.
Why the int 1 goes to another number but 2.3 still good.
How can I modify my code to implement the forward?
Thanks for your time.
fun1 needs a list of arguments to match its format, but when call it from fun2 you give it a va_list. To call it that way you need to rewrite it to take a va_list rather than a ...:
void fun1(const char *fmt, va_list args) {
vfprintf(fmt, args);
}
If you're using gcc, you can avoid many problems of this nature by using -Wall and adding a declaration for your functions that take ...:
extern void fun2(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
This tells gcc that fun2 takes printf-style arguments starting from the second argument with the first argument as the format. With this, it will warn you if the arguments passed to fun1 don't match the format string.
As suggtested by StoryTeller - Unslander Monica and Chris Dodd, My finial code looks like follows.
// before modify
// vprintf <-- fun1 <-- fun2
// after modify
// vprintf <-- vfun1 <--- fun1
// |- fun2
#include <stdio.h>
#include <stdarg.h>
void vfun1(const char *msg, va_list arg_list)
{
printf("this is vfun1\n");
vprintf(msg, arg_list);
}
void fun1(const char *msg, ...) // try to forward vprintf, but implemented by call vfun1
{
printf("this is fun1\n");
va_list arg_list;
va_start(arg_list, msg);
vfun1(msg, arg_list);
va_end(arg_list);
}
void fun2(const char *msg, ...) // try to forward fun1, but implemented by call vfun1
{
printf("this is fun2\n");
va_list arg_list;
va_start(arg_list, msg);
vfun1(msg, arg_list);
va_end(arg_list);
}
int main()
{
printf("------------------------------------\n");
fun1("this is int %d, float %f\n", 5, 2.3);
printf("------------------------------------\n");
fun2("this is int %d, float %f\n", 5, 2.3);
return 0;
}
I would like to send callbacks with different signatures for the same function. Somenthing like this:
#include <stdio.h>
#include <stdarg.h>
void a(int pa) {}
void b(int pb1, float pb2) {}
// exec implementation
int main() {
exec(a, 1);
exec(b, 1, 2.3);
}
I thought of using something like:
void exec(void (*func)(...), ...) {
int arg1;
float arg2;
va_list valist;
va_start(valist, size);
arg1 = va_arg(valist, int);
if (size == 1) {
(*func)(arg1);
va_end(valist);
return;
}
arg2 = va_arg(valist, float);
if (size == 2) {
(*func)(arg1, arg2);
va_end(valist);
return;
}
}
But obviously it doesn't work :(
The usual solution to making callback function interfaces flexible with respect to data provided to the function is to give the callback signature a void * parameter (possibly in addition to other parameters). Arbitrary data can be provided via such a parameter. Something like this:
void exec(void (*func)(void *), void *data) {
func(data);
}
struct s2 {
int i;
float f;
};
void func1(void *data) {
int i = *(int *)data;
// ...
}
void func2(void *data) {
struct s2 s = *(struct s2 *)data;
// ...
}
int main(void) {
int i = 42;
struct s2 s = { .i = 17, .f = 3.14 };
exec(func1, &i);
exec(func2, &s);
}
HOWEVER, It is possible to do something more like you describe, where the callback functions genuinely have different signatures, by specifying the callback type without a prototype. In that case, there are still at least these caveats:
If the callback functions themselves are defined with prototypes (as they should be) then the parameter types should not be any that are altered by the default argument promotions. So, pointers, ints, doubles, but not floats or short ints or chars (not an exhaustive list). If you wanted to support other parameter types then you would need to cast the function pointer before calling the function, as described later.
The callback functions cannot be variadic.
If the front-end is variadic, then it needs to be told at runtime, somehow, what the actual number and types of the arguments are.
Furthermore, there will need to be explicit calls to the callback functions, with correct arguments, so there can be only a fixed set of predetermined callback signatures supported.
For example, that might look something like this:
enum sig { INT, INT_DOUB };
void exec(void (*func)(/* no prototype */), enum sig cb_sig, ...);
void a(int pa) {}
void b(int pb1, double pb2) {}
int main(void) {
exec(a, INT, 1);
exec(b, INT_DOUB, 1, 2.3);
}
void exec(void (*func)(/* no prototype */), enum sig cb_sig, ...) {
va_list valist;
va_start(valist, cb_sig);
switch (cb_sig) {
case INT: {
int i = va_arg(valist, int);
func(i);
break;
}
case INT_DOUB: {
int i = va_arg(valist, int);
double d = va_arg(valist, double);
func(i, d);
break;
}
default:
assert(("Can't be reached", 0));
}
va_end(valist);
}
It is possible that that would elicit a few warnings, such as about a function declaration that does not provide a prototype, and about calling a (declared, but) unprototyped function. Since you know the signatures by the time you execute the calls, however, you could get rid of the latter kind of warning via appropriate casting. For example,
// ...
case INT: {
int i = va_arg(valist, int);
((void (*)(int))func)(i);
break;
}
// ...
You could change the callbacks to take a single va_list argument:
void a(va_list args)
{
int pa = va_arg(args,int);
}
void b(va_list args)
{
int pb1 = va_arg(args,int);
double pb2 = va_arg(args,double);
}
And have your other function pass the va_list along.
void exec(void (*func)(va_list), ...)
{
va_list valist;
va_start(valist, func);
func(valist);
va_end(valist);
}
You can use va_args to solve this.
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#define exec_func(func, ...) func(__VA_ARGS__)
long func(char *a, int b, long c, long d)
{
printf("a: %s, b: %d, c: %ld, d: %ld\n", a, b, c, d);
return c + d;
}
int main()
{
printf("c + d: %ld\n", exec_func(func, "test", 10, 1000, 1000));
}
I am trying to make a function, which will execute a function with the provided sub arguments in C. Like:
int function(void (*func)(), ...) // add as many arguments you want for 'func()'
{
va_list ptr;
...
func(sub_arguments) // the '...'
}
void *abc(int a) { ... }
void *one(int b, int c) { ... }
int main()
{
function(abc, 73);
function(one, 9, 84);
}
Now, is there a way to somehow make a variable list and add it as the arguments and execute it? If so, how?
I know I phrased the question in a very difficult way, but I just don't get how to do this.
You can either extract each argument in function() and make the relevant call:
#include <stdio.h>
#include <stdarg.h>
void abc(int a) {
printf("abc(%d)\n", a);
}
void one(int b, int c) {
printf("one(%d,%d)\n", b, c);
}
int function(void (*func)(), ...) {
va_list ap;
va_start(ap, func);
if(func == abc) {
int a = va_arg(ap, int);
func(a);
} else if(func == one) {
int b = va_arg(ap, int);
int c = va_arg(ap, int);
func(b, c);
}
va_end(ap);
return 0;
}
int main() {
function(abc, 73);
function(one, 9, 84);
}
Or change your sub-functions to take a va_list, then pass it from function to the sub-function. That is probably the approach I would would take. If want to call your sub-functions directly that write a wrapper for each that accepts a ... argument (like printf() and vpritnf() pair). Note that this requires the sub-functions to have a fixed argument like function() has func.
One option could be to not use a variadic function at all but to use a C11 _Generic selection to call an implementation of function exactly matching the arguments it's supposed to relay on to func.
With this solution you'll get compile time checks that you've supplied compatible arguments instead of getting undefined behavior during runtime if you've made mistakes when supplying the arguments.
#include <stdio.h>
int function_impl_1(void(*func)(int), int a) {
func(a);
return 0;
}
int function_impl_2(void(*func)(int, int), int a, int b) {
func(a, b);
return 0;
}
#define function(X, ...) _Generic((X), \
void(*)(int): function_impl_1, \
void(*)(int, int): function_impl_2 \
)(X, __VA_ARGS__)
void abc(int a) {
printf("abc(%d)\n", a);
}
void one(int b, int c) {
printf("one(%d,%d)\n", b, c);
}
void two(int b, int c) {
printf("two(%d,%d)\n", b, c);
}
int main(void) {
function(abc, 73);
function(one, 9, 84);
function(two, 123, 456);
}
Demo
Variadic macros with zero variadic arguments are problematic. There's a GNU extension, __VA_OPT__ (from C++20), that can be used for that:
#define function(X, ...) _Generic((X), \
void(*)(void): function_impl_0, \
void(*)(int): function_impl_1, \
void(*)(int, int): function_impl_2 \
)((X) __VA_OPT__(,) __VA_ARGS__)
void zero(void) {
puts("zero()");
}
// ...
function(zero);
Demo
Previously I asked How to make a function which receive a function as param in C language. I get an answer Link to the question but this solution is based on the parameters of argument's function. I mean:
int functionToPassAsParameter (int arg1, int arg2){
// do something
}
int functionWhichReceiveFunction (int (*f)(), int arg1, int arg2){
// do something
f(arg1, arg2);
// do something
}
// How to call the function
functionWhichReceiveFunction (&functionToPassAsParameter, 1, 2);
I would like something like:
int functionToPassAsParameter (int arg1, int arg2){
// do something
}
int functionWhichReceiveFunction ( f() ){
// do something
f();
// do something
}
// How to call the function
functionWhichReceiveFunction ( functionToPassAsParameter(arg1, arg2) );
So, when I call the function, I pass the correctly params but when I define the function which receive the other function I do not specify which params I will send to it. Is that possible to make?
EDIT 1:
I wanna achieve pass any function to functionWhichReceiveFunction. Something like:
int function_a (int param1, int param2) { /* Do something */ };
void function_b (char *arg1) { /* Do something */ };
// Call the function with two differents functions regardless return type nor params
int x = functionWhichReceiveFunction ( function_a(param1, param2) );
functionWhichReceiveFunction ( function_b(arg1) );
Define the function to be passed to take a void * as a parameter. That way the function that calls the given function doesn't need to know anything specific about the parameters:
struct params1 {
int arg1;
int arg2;
};
struct params2 {
char *arg1;
char *arg2;
};
int functionToPassAsParameter (void *param){
struct params1 *args = params;
// do something
}
int otherFunctionToPassAsParameter (void *param){
struct params2 *args = params;
// do something
}
int functionWhichReceiveFunction (int (*f)(void *), void *args) {
// do something
f(args);
// do something
}
struct params1 p1 = { 1, 2 };
functionWhichReceiveFunction (&functionToPassAsParameter, &p1);
struct params2 p2 = { "abc", "def" };
functionWhichReceiveFunction (&otherFunctionToPassAsParameter, &p2);
To be able to pass a function with unknown parameters to a function, declare the function that will pass the function as follows:
int g(int (*f)());
The function that is actually passed can have any number of parametes, for example:
int f(int x, void *y);
The call is now as follows:
g(f);
The above means that g passes f, which can have zero or more parameters of any type. This is denoted by the empty parameter list.
A particular function that may need to be passed is for example f.
Now g is called with function f, or any other function.
Note that it is up to g to know which parameters must be passed in calling f. So you need a "protocol" that tells g which function/type is passed. For example, besides passing the function, pass an identifier (int) that says what type of function is passed, for example:
#define fS_I_I 1 // f needs String, int, Int
#define fD_I 2 // f needs Double, Int
#define fI_I 3 // f needs Int, Int
int g(int ID, int (*f)());
g(fI_I, f);
Learn more about closures and tagged unions. Notice that C don't have them. You might want to emulate that with callbacks
I wanna achieve pass any function to functionWhichReceiveFunction
You cannot do that simply and portably. Remember that the signature of a function in C is related to its calling conventions (so to the ABI used by your compiler and your code; for examples, look into Linux x86 ABIs; so floating point arguments could be passed in different registers as integral arguments, so your compiler needs to know the signature of all your function pointers). You need to also give to functionWhichReceiveFunction something which describes the signature.
What you might consider doing, assuming your platform have function pointers of the same size and in the same address space as data pointers (this is very often the case), is to pass to functionWhichReceiveFunction a void* pointer (actually, a function pointer casted to void*) and an enumeration describing it.
For example
enum funsig_en {
funsig_void_to_void,
funsig_int_to_void,
funsig_int_to_double,
funsig_int_double_to_void,
};
Then, you'll have corresponding function signatures (types)
typedef void fun_void_to_void(void);
typedef void fun_int_to_void(int);
typedef double fun_int_to_double(int);
typedef void fun_int_double_to_void(int, double);
Suppose you have these static functions
static void statf_void_to_void(void);
static void statf_int_to_void(int);
static double statf_int_to_double(int);
static void statf_int_double_to_void(int, double);
You might declare
void
functionWhichReceiveFunction (void*res, enum funsig_en sigkind, void*fun, ...);
and you could use it as
functionWhichRecieveFunction(NULL, funsig_void_to_void
(void*)statf_void_to_void);
or
functionWhichRecieveFunction(NULL, funsig_int_to_void,
(void*)statf_int_to_void, 123);
or
double r = 0;
functionWhichRecieveFunction(&r, funsig_int_to_double,
(void*)statf_int_to_double, 2345);
I leave you to code that variadic functionWhichRecieveFunction. You need stdarg(3) facilities. It would include code like
va_args arglist;
va_start (arglist, fun);
switch(sigkind) {
case funsig_int_to_void: {
int a = va_arg(arglis, int);
fun_int_to_void* fptr = (fun_int_to_void*)fun;
(*fptr)(a);
return;
} // end case funsig_int_to_void
much later you'll need some va_end(arglis); near the end of your functionWhichRecieveFunction body.
Another possibility is using varargs. In the following example every function being called does its own interpretation of parameters.
#include <stdio.h>
#include <stdarg.h>
// expects 4 arguments (int, int, int, char*)
void f1(va_list args) {
int a, b, c;
char *d;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, int);
d = va_arg(args, char *);
printf("%d, %d, %d: %s\n", a, b, c, d);
}
// expects 3 ars (int, int, char*);
void f2(va_list args) {
int a, b;
char *c;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, char *);
printf("%d, %d: %s\n", a, b, c);
}
void caller(void (*f)(va_list), ...) {
va_list args;
va_start(args, f);
f(args);
va_end(args);
}
int main() {
caller(&f1, 0, 1, 3, "hello");
caller(&f2, 1, 2, "bye");
return 0;
}
Another possibility is to have caller to interpret parameters based on some type info and call a correct function call. This might be useful if you have a limited number of argument patterns and just regular functions to call:
void f3(int a, int b, int c, char *d) {
printf("%d, %d, %d: %s\n", a, b, c, d);
}
void f4(int a, int b, char *c) {
printf("%d, %d: %s\n", a, b, c);
}
typedef enum {
type1, type2
} Types;
void caller1(Types t, void (*f)(), ...) {
va_list args;
va_start(args, f);
switch (t) {
case type1: {
int a, b, c;
char *d;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, int);
d = va_arg(args, char *);
f(a,b,c,d);
break;
}
case type2: {
int a, b;
char *c;
a = va_arg(args, int);
b = va_arg(args, int);
c = va_arg(args, char *);
f(a,b,c);
}
}
va_end(args);
}
int main() {
caller1(type1, &f3, 3,2,1, "hi");
caller1(type2, &f4, 3,2,"take care");
return 0;
#Paul Ogilvie, this is the code:
int f(int x, void *y) {
return x;
};
int g(int (*f)()) {
int x = f(1, NULL); // call f with parameters
printf("X is: %d", x);
return(x); // return result
};
int main()
{
//g( f(1, 2) ); // this passes the result of a call to f, not f
g( f ); // this passes f
return 0;
}
There some code in one gstreamer-plugin:
static GstFlowReturn
gst_ebml_peek_id_full (GstEbmlRead * ebml, guint32 * id, guint64 * length,
guint * prefix)
{
GstFlowReturn ret;
ret = gst_ebml_peek_id_length (id, length, prefix,
(GstPeekData) gst_ebml_read_peek, (gpointer) gst_ebml_read_br (ebml),
ebml->el, gst_ebml_read_get_pos (ebml));
if (ret != GST_FLOW_OK)
return ret;
GST_LOG_OBJECT (ebml->el, "id 0x%x at offset 0x%" G_GINT64_MODIFIER "x"
" of length %" G_GUINT64_FORMAT ", prefix %d", *id,
gst_ebml_read_get_pos (ebml), *length, *prefix);
Now see the 4:th argument to gst_ebml_peek_id_length () is
(GstPeekData) gst_ebml_read_peek
where gst_ebml_read_peek is another function whose definition is:
static const guint8 *
gst_ebml_read_peek (GstByteReader * br, guint peek)
{
const guint8 *data = NULL;
if (G_LIKELY (gst_byte_reader_peek_data (br, peek, &data)))
return data;
else
return NULL;
}
Now I want to ask you is: gst_ebml_read_peek has two input argument in definition, so how can it be called (in the upper code) without arguments?
Edit:
You can find this code at
http://gstreamer.freedesktop.org/data/coverage/lcov/gst-plugins-good/gst/matroska/ebml-read.c.gcov.html
From around line 194.
Because it's a function pointer. The function is not actually called at that point, it's just passed to gst_ebml_peek_id_length (which will likely call it later with the correct arguments).
Here is a simpler example doing a similar thing:
#include <stdio.h>
typedef int (*binaryop)(int, int);
static int add(int a, int b) {
return a + b;
}
static int mul(int a, int b) {
return a * b;
}
static void print_result(binaryop op, int a, int b) {
printf("%d\n", op(a, b));
}
int main() {
print_result(add, 2, 3);
print_result(mul, 5, 7);
return 0;
}
The print_result function takes another function as a parameter, which it then calls. When you just write add without the parentheses, the function is not yet called. It is only called in a function call expression, and that looks like this: function_name(arguments).
Argument passed to gst_ebml_peek_id_full() is function pointer of gst_ebml_read_peek() or in other terms its just passing the handle of the function so that gst_ebml_peek_id_full() can call passed in function with correct parameter.
Gives flexibility of passing your own/different implementation of function which implements same prototype of gst_ebml_read_peek().