I am trying to implement low-level code that passes variadic arguments to a function pointer (with the function defined in NASM). This pointer can change at any time, so I need to declare a function pointer with the following signature:
typedef int (__fastcall* callback)(...);
However, unless I declare it with a non-variadic parameter (which wont work), the compiler outputs the error "error : expected a type specifier". Is there any way to fix this just using C? Is there a different implementation that would work short of adjusting all of the other parameters based on calling convention in assembly? Any ideas or solutions would be appreciated.
Edit: I'm aware that this is a very hacky implementation, but I am working with a legacy codebase. So as much as I'd like to, I can't completely change how everything works as I need a solution which will work in the current codebase.
Related
I am presently in a case where I need to call a lot of function pointers that has been extracted at runtime. The problem is that the arguments are unknown at compilation time.
But, at runtime I receive datas that allows me to know the arguments of the function and I can even store the arguments in a char* array. The problem is that I don't have a function pointer model to cast it into.
In high level language, I know there is function like "InvokeMethode(String name,Byte[] args)" that interpret the bytes array like arguments. Since reflection does not exist in C, I have no hope to see this with a function pointer.
One solution that I have in mind (and it's really bad), is to create a model of function pointer at compilation time that will cast in a "hardcoded way" the ptr to the right type to use like this:
void callFunc64Bits(void* funcPtr,long long args);
void callFuncVoid(void* funcPtr);
The problem is that I will have to create like 100 function like this that will cast the pointer correctly.
Is there a way to do it more efficiently?
Thank you very much!
This is a hard problem without, unfortunately, good or easy answers.
See this former SO question: Run-time parameters in gcc (inverse va_args/varargs)
See this C FAQ question: http://c-faq.com/varargs/invvarargs.html
See this collection of "wacky ideas" by the C FAQ list maintainer: http://c-faq.com/varargs/wacky.html
Addendum: see this former SO question: How to call functions by their pointers passing multiple arguments in C?
...which mentions "libffi": http://sourceware.org/libffi/
Hey I have implemented some callbacks in my C program.
typedef void (*server_end_callback_t)(void *callbackArg);
then I have variable inside structure to store this callback
server->server_end_callback = on_sever_end;
What I have noticed it that I can pass in on_server_end callback function implementation that skips void *callbackArg and the code works correctly (no errors).
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
void on_server_end(void) {
// some code goes here
}
I believe it is an undefined behavior from the C point of view, but it works because of the calling convention you are using.
For example, AMD64 ABI states that the first six arguments get passed to the calling function using CPU registers, not stack. So neither caller nor callee need no clean-up for the first six arguments and it works fine.
For more info please refer the Wikipedia.
The code works correctly because of the convention of passing arguments. Caller knows that callee expects some arguments - exactly one. So, it prepares the argument(s) (either in register or on stack - depending on ABI on your platform). Then callee uses those parameters or not. After return from callee, caller cleans up the stack if necessary. That's the mistery.
However, you shall not abuse this specific behaviour by passing incompatible function. It is a good practice to always compile your code with options -W -Wall -Werror (clang/gcc and compatible). Enabling such option would provide you a compilation error.
C allows a certain amount of playing fast and loose with function arguments. So
void (*fptr) ();
means "a pointer to a function which takes zero or more arguments". However this is for backwards compatibility, it's not wise to use it in new C code. The other way round
void (*fptr)(void *ptr)
{
/* don't use the void */
}
/* in another scope */
(*fptr)(); /* call with no arguments */
also works, as long as you don't use the void *, and I believe it is guaranteed to work though I'm not completely sure about that (on a modern machine the calling convention is to pass the first arguments in registers, so you just get a garbage register, and it will work). Again, it is a very bad idea to rely on it.
You can pass a void *, which you then cast to a structure of appropriate type containing as many arguments as you wish. That is a good idea and a sensible use of C's flexibility.
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
No it is not. Any function with a given function declaration is not compatile with a function of a different function declaration. This rule applies for pointers to functions too.
So if you have a function such as pthread_create(..., my_callback, ...); and it expects you to pass a function pointer of type void* (*) (void*), then you cannot pass a function pointer of a different format. This invokes undefined behavior and compilers may generate incorrect code.
That being said, function pointer compatibility is a common non-standard extension on many systems. If the calling convention of the system is specified in a way that the function format doesn't matter, and the specific compiler port supports it, then such code might work just fine.
Such code is however not portable and not standard. It is best to avoid it whenever possible.
I've just discovered variadic functions in C and have defined one as a general notification typedef, that as well as a pointer to a text string can optionally have whatever arguments sent along with it- useful as a generic debug function for instance where I want all the output string manipulation in one place.
Since I want my C files to be as generic as possible I have static variables that contain pointers to possible callbacks in higher code, populated in an init call. Since the pointers may be null if higher code isn't interested, I'd normally have a local wrapper that only calls through the pointer if it's not null. But I'm having trouble figuring out how to forward this fuzzy thing represented by '...' and simply calling the function with '...' in the argument list gives a syntax error.
Is there any way to do this, or am I stuck with having a dummy local handler and having init set null callbacks to a pointer to that?
You can't pass on the variadic arguments. You have to fetch them into a va_list and pass this to the inner function.
Take a look at this Question at the C FAQ. It defines a variadic error function that wants to forward to printf. This is just your use case.
In the same FAQs, it is generally recommended to have a version taking va_list for every (or most) variadic functions
I'm trying to make some improvements to a interpreter for microcontrollers that I'm working on. For executing built-in functions I currently have something like this (albeit a bit faster):
function executeBuiltin(functionName, functionArgs) {
if (functionName=="foo") foo(getIntFromArg(functionArgs[0]));
if (functionName=="bar") bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2]));
if (functionName=="baz") baz();
...
}
But it is for an embedded device (ARM) with very limited resources, and I need to cut down on the code size drastically. What I'd like to do is to have a general-purpose function for calling other functions with different arguments - something like this:
function executeBuiltin(functionName, functionArgs) {
functionData = fast_lookup(functionName);
call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs);
}
So I want to be able to call a standard C function and pass it whatever arguments it needs (which could all be of different types). For this, I need a call_with_args function.
I want to avoid re-writing every function to take argc+argv. Ideally each function that was called would be an entirely standard C function.
There's a discussion about this here - but has anything changed since 1993 when that post was written? Especially as I'm running on ARM where arguments are in registers rather than on the stack. Even if it's not in standard C, is there anything GCC specific that can be done?
UPDATE: It seems that despite behaviour being 'undefined' according to the spec, it looks like because of the way C calls work, you can pass more arguments to a function than it is expecting and everything will be fine, so you can unpack all the arguments into an array of uint32s, and can then just pass each uint32 to the function.
That makes writing 'nice' code for calls much easier, and it appears to work pretty well (on 32 bit platforms). The only problem seems to be when passing 64 bit numbers and compiling for 64bit x86 as it seems to do something particularly strange in that case.
Would it be possible to do at compile time with macros?
Something along the lines of:
https://www.redhat.com/archives/libvir-list/2014-March/msg00730.html
If runtime was required, perhaps __buildin_apply_args() could be leveraged.
from this document, section 5.5, Parameter Passing, it seems like parameters are passed both in registers and in stack, as with most of today platforms.
With "non standard C" I am thinking to pack the parameters and call the function following the documentation with some asm(). However you need a minimal information about the signature of the function being called anyway (I mean, how many bits for each argument to be passed).
From this point of view I would prefer to prepare an array of function names, an array of function pointers and an array of enumerated function signatures (in the number of bits of each argument... you don't need to differentiate void* from char* for example) and a switch/case on the signatures, and a switch/case on the last one. So I have reported two answers here.
You can do a very simple serialization to pass arbitrary arguments. Create an array and memcpy sizeof(arg) bytes into it for each passed argument.
Or you can create structs for function arguments.
Every function takes a char* or a void*. Then you pass either a pointer to a struct with that functions parameters, or you define a set of macros or functions to encode and decode arbitrary data from an array and pass the pointer to that array.
Quick question:
strlen[char*] works perfectly regardless whether I #include <string.h> or not
All I get from compiler is a warning about implicit declaration, but functionally it works as intended.
Why is that?
When you invoke undefined behavior, one possible behavior is that the program behaves as you expected it to, one your system, and with the current version of libraries and system software you have installed. This does not mean it's okay to do this. Actually a correct C99 compiler should not allow implicit function declarations; it should give you an error.
The function prototypes in C are not compulsory. They're useful indications to the compiler so that it can do type checking on types which are passed into them. When you don't include string.h, a default signature is assumed for the function which is why you get the warning.
If a function is called without a prototype in scope, the compiler will generate code to call a function which accepts whatever types of parameters are passed and accept an integer result. If the parameters match those the function expects, and if the function returns its result in a way the calling code can handle(*), all will be well. The purpose of prototyping is to ensure that arguments get converted into expected types if possible, and that compilation will fail if they cannot be converted. For example, if a non-prototyped function expects an argument of type 'long' and one attempts to pass an 'int', any of the following may occur:
The program may crash outright
Things may work as expected
The function may execute as though it were passed some arbitrary different parameter value
The program may continue to run, but with arbitrary values corrupting any or all program variables.
The computer may cause demons may fly out the programmer's nose
By contrast, if the function were prototyped, the compiler would be guaranteed to do whatever was necessary to convert the 'int' to a 'long' prior to calling the function.
When C was originally conceived, prototypes didn't exist, and the programmer was responsible for ensuring that all arguments were passed with the precise types expected. In practice, it's a real pain to ensure that all function arguments are always the exact proper types (e.g. when passing the value five to a function that expects a long, one must write it as either "5L" or "(long)5"). Realistically speaking, there's never(**) any reason to rely upon implicit argument types, except with variadic functions.
(*) Any of the things that can happen with incorrect parameter types can happen with incorrect return types, except when a function is expected to return 'int' and the actual return value of the function would fit in an 'int', the results are more likely to be correct than when incorrect parameter types are used.
(**) The only exceptions I can think of would be if one was programming for some really old hardware for which a prototype-aware compiler was unavailable, or if one was programming for a code-golf or similar competition. The latter I consider puzzle-solving rather than programming, and I'm unaware of any hardware people would be interested in using for which the former condition would apply.
Because it's declaration ie equal to so called 'default declaration'. Compiler expects any unknown function to return int and expect parameters as passed at the first time of function usage in code.
Usually this is because another header file which you have included ALSO includes string.h. Obviously it is bad practice to assume that you don't need to include something just because something else does, but it is most likely responsible for this effect.
I guessing it's because in C an int is the default data type returned from a function.
Can you give a fuller code example.
The function prototype is there in include files. So even if you don't include those files, a fixed prototype int function_name(); is written. Now the code of strlen() is there in the library files which are linked at run time, so the function gives correct output (only if it is the only function with a fixed prototype int function_name();).