I don't know how to accomplish this!
how to get the function pointer in va_list arguments?
thanks so much.
Typedefs often make working with function pointers easier, but are not necessary.
#include <stdarg.h>
void foo(int count, ...) {
va_list ap;
int i;
va_start(ap, count);
for (i = 0; i < count; i++) {
void (*bar)() = va_arg(ap, void (*)());
(*bar)();
}
va_end(ap);
}
Use a typedef for the function pointer type.
Related
I would like to know how I would go about passing any function to a function, as in a generic function pointer that can take any function whatsoever, The goal of this is to make a destructor system, so basically storing the function and calling it with it's arguments also stored later down the line,
Something like:
Defer(SDL_DestroyWindow, Window);
I already handled the arguments, but I don't know how to manage the function pointer part of this, Thank you!
Edit: I added more info ...
typedef struct {
void** args;
} IM_Defer_Resource;
/* Defer & Whatnot */
IM_Stack* IM_Defer_Stack;
void IM_Defer_Init() {
IM_Defer_Stack = IM_Stack_Init();
}
void IM_Defer(/* What to put here? */) {
}
void IM_Defer_All() {
while(IM_Defer_Stack->size) {
IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
if(!resource) continue;
/* What to do */
}
}
I don't have the actual functions of defer, but I did copy every argument into the stack and can pop them successfully, I don't know how to implement the variadic function calling though
Edit2:
After receiving some input: I think this would be more feasible:
Defer(SDL_DestroyWindow, "SDL_Window*", window);
I am brainstorming how this would be possible, but I would appreciate some input
Edit3:
/* Defer & Whatnot */
typedef struct {
char** types;
void** args;
int count;
} IM_Defer_Resource;
IM_Stack* IM_Defer_Stack;
void IM_Defer_Init() {
IM_Defer_Stack = IM_Stack_Init(IM_Get_Stack_Type(IM_Defer_Resource));
}
void IM_Defer_Internal(void* var, int n, ...) {
char* type;
void* arg;
va_list args;
va_start(args, n);
IM_Defer_Resource resource;
int count = n / 2;
resource->types = calloc(count, sizeof(char*));
resource->args = calloc(count, sizeof(void*));
resource->count = count;
for(count > 0; n -= 1) {
type = va_arg(args, char*);
resource->types[count-1] = type;
arg = va_arg(args, void*);
resource->args[count-1] = arg;
}
IM_Stack_Push(IM_Defer_Stack, &resource);
}
void IM_Defer_All() {
while(IM_Defer_Stack->size) {
IM_Defer_Resource* resource = IM_Stack_Pop(IM_Defer_Stack);
if(!resource) continue;
/* I have a char* and a void* to the resource, Now what? */
free(resource->types);
free(resource->args);
}
}
This is what I came up with, but I am wondering how I can conver that char* into a type...
As I said in comment a big problem is that when declaring a variadic function the undeclared parameters are subject to the default argument promotions. This means that you can find the passed arguments different from that intended by the function, that will eventually lead to exceptions. What you want to do is feasible, but really very complex.
One solution, but limited because requires a lot of coding, could be:
#include <stdarg.h>
#include <stdio.h>
typedef enum { fn1, fn2, fn3, /*....*/} e_fn;
void multi_fun(e_fn fn, ...)
{
va_list ap;
int j;
va_start(ap, fn); /* Requires the last fixed parameter (to get the address) */
switch(fn)
{
case fn1:
{
//suppose prototype for fn1 to be void fn1_fn(int, float, struct mystruct *);
int this_int = va_arg(ap, int);
float this_float = va_arg(ap, float);
struct mystruct *this_struct = va_arg(ap, struct mystruct *);
fn1_fn(this_int, this_float, this_struct);
break;
}
case fn2:
{
...
}
}
va_end(ap);
}
You should take a look at Fake Function Framework (fff) on GitHub. They've done this using macros for caching mock functions. MIT Licensed. However, just like #Frankie_C said, this requires a LOT of code. The header file that defines all of the macros is around 6K LOC. And functions are still limited to 20 arguments.
I am making a C library that creates a print function, which basically executes printf. Because of this, I wish to create a duplicate of printf from glibc, but with the name print. How can I duplicate this function without duplicating all of it's code?
(I found the code here but don't understand how to duplicate it in my library, or if it is legal to do so.)
There you go:
#include <stdarg.h>
void println(const char* format,...)
{
va_list args;
va_start(args,format);
vprintf(format,args);
printf("\n");
va_end(args);
}
You can use a variadic macro:
#define println(...) (printf(__VA_ARGS__), (void) puts(""))
You can either use a Macro:
#define print printf
or define a wrapper function
int print( char *fmt, ... )
{
va_list ap;
int n;
va_start(ap, fmt);
n = vprintf(fmt, ap);
va_end(ap);
return n;
}
I am trying to pass a function pointer as part of a number of arguments under va_arg. I tried using a void * wildcard, before typecasting it later, but that gives an error.
fn_ptr = va_arg(*app, (void*));
How does one pass a function pointer, as an argument to another function using va_args?
Just pass the type of the function pointer to va_arg. For example:
#include <stdio.h>
#include <stdarg.h>
void foo()
{
printf("foo\n");
}
typedef void(*foo_ptr)();
void bar(unsigned count, ...)
{
va_list args;
va_start(args, count);
unsigned i = 0;
for (; i < count; ++i) {
foo_ptr p = va_arg(args, foo_ptr);
(*p)();
}
va_end(args);
}
int main()
{
bar(2, &foo, &foo);
}
Live demo
So, here's a small problem I'm facing right now -> I'm trying to write a function that will accept a char* message and a variable number of arguments. My function will modify the message a little, and then It'll call printf with the message and given parameters. Essentialy, I'm trying to write something like that:
void modifyAndPrintMessage(char* message,...){
char* newMessage; //copy message.
//Here I'm modifying the newMessage to be printed,and then I'd like to print it.
//passed args won't be changed in any way.
printf(newMessage,...); //Of course, this won't work. Any ideas?
fflush(stdout);
}
So, anybody knows what should I do to make it happen? I'd be most grateful for any help :)
You want to use varargs...
void modifyAndPrintMessage( char* message, ... )
{
// do somehthing custom
va_list args;
va_start( args, message );
vprintf( newMessage, args );
va_end( args );
}
void modifyAndPrintMessage(char* message,...)
{ char newMessage[1024]; // **Make sure the buffer is large enough**
va_list args;
va_start(args, message);
vsnprintf(newMessage, message, args);
printf(newMessage);
fflush(stdout);
}
Use varargs to accept variable number of parameters then use sprintf to create the new message
You can use va_list from stdarg.h,
C example: http://www.tutorialspoint.com/cprogramming/c_variable_arguments.htm
C++ example: http://www.cprogramming.com/tutorial/lesson17.html.
An of course, see the man page: http://linux.die.net/man/3/stdarg
Man page example for reference:
#include <stdio.h>
#include <stdarg.h>
void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
There is a library which includes this functionality. Here is some example code from the reference:
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
int FindMax (int n, ...)
{
int i,val,largest;
va_list vl;
va_start(vl,n);
largest=va_arg(vl,int);
for (i=1;i<n;i++)
{
val=va_arg(vl,int);
largest=(largest>val)?largest:val;
}
va_end(vl);
return largest;
}
The ellipsis is actually valid code, and you can use the va_list object to parse a variable number of parameters.
What does this mean?
void message(int x, int y, ...)
I can't understand what ... is.
Can anybody explain?
... denotes a variable list of arguments that can be accessed through va_arg, va_end and va_start.
Unspecified/variable number of parameters. To handle such function you have to use the va_list type and va_start, va_arg, and va_end functions:
An example taken from here:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
main(){
f();
exit(EXIT SUCCESS);
}
int maxof(int n args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
You can find more details here
You have defined a function message somewhere that takes at least two arguments of type int and then some optional arguments indicated by the "...". (printf is another function taking optional arguments).
The optional arguments can be accessed using the va_* functions.
... represents final argument passed as an array or as a sequence of arguments.
It's the variable argument formal parameter. From the syntactical prospective it allows you pass a variable number of parameters (at least two, which are x and y, but even more).