Casting a void pointer (data) to a function pointer - c

I know this has been asked before but none of the cases I've seen here are like this one.
I am importing some API functions at runtime, the general declaration on those functions would be like:
// Masks for UnmapViewOfFile and MapViewOfFile
typedef BOOL (WINAPI *MyUnmapViewOfFile)(LPCVOID);
typedef LPVOID (WINAPI *MyMapViewOfFile)(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
// Declarations
MyUnmapViewOfFile LoadedUnmapViewOfFile;
MyMapViewOfFile LoadedMapViewOfFile;
I then call a generic "load" function where it calles GetProcAddress to get the address of the exported function from the proper DLL. That address is returned on a void**. This void** is one of the parameters in the generic load, something like:
int GenericLoad(char* lib, void** Address, char* TheFunctionToLoad)
and I would call this function:
void *Address;
GenericLoad("kernel32.dll", &Address, "UnmapViewOfFile");
LoadedUnmapViewOfFile = (MyUnmapViewOfFile) Address;
Or something similar to this.
Now, of course the compiler complains about trying to cast a data void* to a function pointer. How do I do this then?
I've read countless sites and all kinds of nasty casts, so I'd appreciate it if you add code to the explanation.
Thanks
Jess

The correct code would be this one line:
GenericLoad("kernel32.dll", (void**)&LoadedUnmapViewOfFile, "UnmapViewOfFile");
What is done here basically is this: the address of the pointer variable (the one in which you want the address of the function to be put) is passed to GenericLoad - which is basically what it expects. void** was to denote "give me the address of your pointer". All the type casting is a magic around it. C would not allow specifying "a pointer to any function pointer", so the API author preferred void**.

Now, of course the compiler complains about trying to cast a data void* to a function pointer
My compilers don't complain at all with your code (then again, I don't have warnings cranked up - I'm using more-or-less default options). This is with a variety of compilers from MS, GCC,and others. Can you give more details about the compiler and compiler options you're using and the exact warning you're seeing?
That said, C doesn't guarantee that a function pointer can be cast to/from a void pointer without problems, but in practice this will work fine on Windows.
If you want something that's standards compliant, you'll need to use a 'generic' function pointer instead of a void pointer - C guarantees that a function pointer can be converted to any other function pointer and back without loss, so this will work regardless of your platform. That's probably why the return value of the Win32 GetProcAddress() API returns a FARPROC, which is just a typedef for a function pointer to a function that takes no parameters (or at least unspecified parameters) and returns a pointer-sized int. Something like:
typedef INT_PTR (FAR WINAPI *FARPROC)();
FARPROC would be Win32's idea of a 'generic' function pointer. So all you should need to do is have a similar typedef (if you don't want to use FARPROC for some reason):
typedef intptr_t (*generic_funcptr_t)(); // intptr_t is typedef'ed appropriately elsewhere,
// like in <stdint.h> or something
int GenericLoad(char* lib, generic_funcptr_t* Address, char* TheFunctionToLoad)
generic_funcptr_t Address;
GenericLoad("kernel32.dll", &Address, "UnmapViewOfFile");
LoadedUnmapViewOfFile = (MyUnmapViewOfFile) Address;
Or you can dispense with the middle-man and pass the pointer you really want to get the value into:
GenericLoad2("kernel32.dll", (generic_funcptr_t *) &LoadedUnmapViewOfFile, "UnmapViewOfFile");
Though that's more dangerous than the method using the intermediate variable - for example the compiler will not give a diagnostic if you leave off the ampersand in this last example, however in the previous example, it would generally give at least a warning if you left off the ampersand from the Address argument. Similar to Bug #1 here: http://blogs.msdn.com/sdl/archive/2009/07/28/atl-ms09-035-and-the-sdl.aspx
Now you should be set. However, any way you look at it you'll need to perform some dangerous casting. Even in C++ with templates you'd have to perform a cast at some level (though you might be able to hide it in the template function) because the GetProcAddress() API doesn't know the actual type of the function pointer you're retrieving.
Also note that your interface for GenericLoad() has a possibly serious design problem - it provides no way to manage the lifetime of the library. That may not be a problem if your intent is to not allow unloading a library, but it's something that users may want so you should consider the issue.

Addresses to data and addresses to functions are incompatible things. I believe that your Address variable must be a function pointer as in your BOOL definition: (WINAPI *MyUnmapViewOfFile)(LPCVOID). This type of declaration is required because in order to have a pointer to a function, the return type, and the type and number of arguments must be known. This is because when you call your function, the correct amount of space must be allocated on the stack to contain these return value and args.
Given that, I believe that the correction in Pavel's answer is correct (FYI, his (void**) cast is a type safety measure).

Related

Passing uint8_t instead of uint32_t into a function (in C)

Going over some code (written in the C language) I have stumbled upon the following:
//we have a parameter
uint8_t num_8 = 4;
//we have a function
void doSomething(uint32_t num_32) {....}
//we call the function and passing the parameter
doSomething(num_8);
I have trouble understanding if this a correct function calling or not. Is this a casting or just a bug?
In general, I know that in the C / C++ languages only a copy of the variable is passed into the function, however, I am not sure what is actually happening. Does the compiler allocates 32 bits on the stack (for the passed parameter), zeros all the bits and just after copies the parameter?
Could anyone point me to the resource explaining the mechanics behind the passing of parameter?
As the function declaration includes a parameter type list, the compiler knows the type of the expected parameter. It can then implicitely cast the actual parameter to the expected type. In fact the compiler processes the function call as if it was:
doSomething((uint32_t) num_8);
Old progammers that once used the (not so) good K&R C can remember that pre-ansi C only had identifier lists and the type of parameters was not explicitely declared. In those day, we had to explicitely cast the parameters, and when we forgot, we had no compile time warnings but errors at execution time.
The way the cast and the call is precisely translated in assembly language or machine instruction is just an implementation detail. What matters is that everything must happen as if the compiler had declared a temporary uint32_t variable had coerced the uint8_t value into the temporary and had passed the temporary to the function. But optimizing compilers often use a register to pass a single integer parameter. Depending on the processor, it could zero the accumulator, load the single byte in the low bits and call the function.

What does *(void **) (&funcp) do in this line of code involving dlsym()?

Could somebody help me interpret this line of code (from here)?
*(void **) (&funcp) = dlsym(libHandle, argv[2]);
I do not understand what *(void **) (&funcp) does.
This might clarify it (from here):
(Update: I didn't include the exact same link to be snarky. I missed the link in the original question. :P)
/* The rather clumsy cast above is necessary because the ISO C standard
does not require that pointers to functions can be cast back and
forth to 'void *'. (See TLPI pages 863-864.) SUSv3 TC1 and SUSv4
accept the ISO C requirement and propose casts of the above
form as the workaround. However, the 2013 Technical Corrigendum
(TC1) to SUSv4 requires casts of the following more natural form
to work correctly:
funcp = (void (*)()) dlsym(libHandle, argv[2]);
Various current compilers (e.g., gcc with the '-pedantic' flag)
may still complain about such casts, however. */
It's basically a hack to avoid having to cast the void* from dlsym() to a function pointer, by instead reinterpreting the data in funcp as a void* and storing into that. This is done by taking the address of funcp (the address of the variable itself), pretending that the address refers to a void* (via the (void**) cast), dereferencing it, and storing the void* from dlsym() into it. Simpler forms are likely to work in practice too.
This method of "reinterpreting" data by taking its address, casting that address to a pointer to a different type, and dereferencing, is often called type punning by the way. The pun comes from the same data having different meanings when interpreted in different ways, which is how real puns work too.
(Type punning can be unsafe in certain circumstances, including when the compiler makes use of strict aliasing rules, which lets it assume that certain pointers of different type do not alias (that they do not refer to the same data). The cast above might violate strict aliasing as you get a function pointer and a void* referring to the same data, though it's a "likely to work in practice" thing in this case.)
(The reason ISO C does not require that function pointers can be safely cast to void pointers and back is probably that functions and data (void pointers refer to "data") are stored separately on some machines. Since they are separate, they might also use different address lengths or formats, so that casting between function pointers and data pointers might not make sense. Architectures that separate code and data in that way are called Harvard architectures.)
dlsym() relates to dlopen() and dlclose() See the man pages.
The line you're seeing it is looking up a symbol (fetching the value of the symbol, and in this case is presuming it is a function address), in the binary object loaded at dlopen(), and assigning it to the pointer variable funcp.
When funcp is typecast to the corresponding function type, meaning given the proper function signature, that function can be called via funcp and parameters passed as well.
dl (dynamic library) set of functions are the mechanism by which plugins are typically facilitated on systems that support dlopen/dlsym/dlclose. The plugin has to conform to an interface defined by the user, or community, that the code that wants to load the plugin must also know, so that knows how to find and define the symbols by name, and how to cast them and use them.
Another way of putting it, is it lets you make calls into an object that isn't available at link time and lets your code do at runtime what the linker handles for you at link time.
dlsym() returns a (void *) because it can't assume anything about the symbol it's loading, which could be a variable, a function entry point, etc... to do anything with the value returned, you generally need to cast it into the type that corresponds to the symbol in the binary loaded with dlopen().

Manually calling C function with arbitrary stack data at run time

I know the reasons why this is a bad idea and I also know that this is the reason C++ templates were created, but I'm doing it in C for the fun and learning.
I'm embedding Python into my application and I wanted to make it possible to register certain C functions, with any arbitrary type, to be callable at the application run-time. Because of this a pointer to them is stored (as a simple void*).
With some basic macro fun I have gotten all the information I need about these functions and stored that too - the function pointer, the size of the return value (and if it is void), the number of arguments and each of their sizes.
So I'm stuck at the final stage - which is the actual calling of the function pointer with the appropriate data. I'm fairly certain this sort of thing should be possible (I've caused stack errors in my own time), but I was wondering if there was a more...legitimate way to do it.
I guess the ideal would look something like this:
void call_function(void* function, void* return, void* arg_data, int arg_data_size);
Does such a thing exists?
Thanks
You can declare a function pointer void* (*f) (void*); that points to a function that takes a void* argument and returns a void* return value -- you can put this in the first parameter of call_function.
Then call call_function as:
void* function(void*);
ret_type ret;
arg_type arg_data;
call_function(&function, (void*)&ret, (void*)&arg_data, sizeof(arg_data));
where arg_type is the actual argument type you want to use inside function and ret_type is the actual type of the return value of function.
Note: you might want to specify the size of the return value type as well.
Note: this will work with any function of one argument. The solution can be extended to a fixed/known number of arguments in function, but not to handle an unknown number of arguments.
Note: naming the second parameter return is not allowed as return is a keyword.

Can you cast a pointer to a function of one type to a function of another type that takes additional arguments?

Can you cast a function pointer of this type:
void (*one)(int a)
to one of this type:
void (*two)(int a, int b)
and then safely invoke the pointed-to function with the additional arguments(s) it has been cast to take? I had thought such a thing was illegal, that both function types had to be compatible. (Meaning the same prototype--same return value, same parameter list.) But that is exactly what this bit of GTK+ code appears to be doing (taken from here):
g_signal_connect_swapped(G_OBJECT(button), "clicked",
G_CALLBACK(gtk_widget_destroy), G_OBJECT(window));
If you look up the "clicked" signal (or just look at other examples of its use from the first link), you will see that its handlers are expected to be declared like this:
void user_function(GtkButton *button, gpointer user_data);
When you register a handler via g_signal_connect_swapped(), the widget pointer and data pointer arguments are swapped in order, thus, the declaration should look like this instead:
void user_function(gpointer user_data, GtkButton *button);
Here is the problem. The gtk_widget_destroy() function registered as a callback is prototyped like this:
void gtk_widget_destroy(GtkWidget *widget);
to take only a single argument. Presumably, because the data pointer (a GtkWindow) and the pointer to the signaling widget (a GtkButton) are swapped, the sole argument it receives will be the window pointer, and the button pointer, which will be passed after, will silently be ignored. Some Googling has turned up similar examples, even the registering of functions like gtk_main_quit() that take no arguments at all.
Am I correct in believing this to be a standards violation? Have the GTK+ developers found some legal magic to make this all work?
The C calling convention makes it the responsibility of the caller to clean up the arguments on the stack. So if the caller supplies too many arguments, it is not a problem. The additional arguments are just ignored.
So yes, you can cast a function pointer to another function pointer type with the same arguments and then some, and call the original function with too many arguments and it will work.
In my opinion, C89 standards in this regard are quite confusing. As far as I know, they don't disallow casting from/to function with no param specification, so:
typedef void (*one)(int first);
typedef void (*two)(int first, int second);
typedef void (*empty)();
one src = something;
two dst;
/* Disallowed by C89 standards */
dst = (two) src;
/* Not disallowed by C89 standards */
dst = (two) ((empty) src);
At the end, the compilers must be able to cast from one to two, so I don't see the reason to forbid the direct cast.
Anyway, signal handling in GTK+ uses some dark magic behind the scenes to manage callbacks with different argument patterns, but this is a different question.
Now, how cool is that, I'm also currently working my way through the GTK tutorial, and stumbled over exactly the same problem.
I tried a few examples, and then asked question What happens if I cast a function pointer, changing the number of parameters , with a simplified example.
The answer to your question (adapted from the excellent answers to my question above, and the answers from question Function pointer cast to different signature):
Yes, this is a violation of the C standard. If you cast a function pointer to a function pointer of an incompatible type, you must cast it back to its original (or a compatible) type before calling it. Anything else is undefined behaviour.
However, what it does in practice depends on the C compiler, especially the calling convention it uses. The most common calling convention (at least on i386) happens to just put the parameters on the stack in reverse order, so if a function needs less parameters than it is supplied, it will just use the first parameters and ignore the rest -- which is just what you want. This will break however on platforms with different calling conventions.
So the real question is why the GLib developers did it like this. But that's a different question I guess...

Function pointer cast to different signature

I use a structure of function pointers to implement an interface for different backends. The signatures are very different, but the return values are almost all void, void * or int.
struct my_interface {
void (*func_a)(int i);
void *(*func_b)(const char *bla);
...
int (*func_z)(char foo);
};
But it is not required that a backends supports functions for every interface function. So I have two possibilities, first option is to check before every call if the pointer is unequal NULL. I don't like that very much, because of the readability and because I fear the performance impacts (I haven't measured it, however). The other option is to have a dummy function, for the rare cases an interface function doesn't exist.
Therefore I'd need a dummy function for every signature, I wonder if it is possible to have only one for the different return values. And cast it to the given signature.
#include <stdio.h>
int nothing(void) {return 0;}
typedef int (*cb_t)(int);
int main(void)
{
cb_t func;
int i;
func = (cb_t) nothing;
i = func(1);
printf("%d\n", i);
return 0;
}
I tested this code with gcc and it works. But is it sane? Or can it corrupt the stack or can it cause other problems?
EDIT: Thanks to all the answers, I learned now much about calling conventions, after a bit of further reading. And have now a much better understanding of what happens under the hood.
By the C specification, casting a function pointer results in undefined behavior. In fact, for a while, GCC 4.3 prereleases would return NULL whenever you casted a function pointer, perfectly valid by the spec, but they backed out that change before release because it broke lots of programs.
Assuming GCC continues doing what it does now, it will work fine with the default x86 calling convention (and most calling conventions on most architectures), but I wouldn't depend on it. Testing the function pointer against NULL at every callsite isn't much more expensive than a function call. If you really want, you may write a macro:
#define CALL_MAYBE(func, args...) do {if (func) (func)(## args);} while (0)
Or you could have a different dummy function for every signature, but I can understand that you'd like to avoid that.
Edit
Charles Bailey called me out on this, so I went and looked up the details (instead of relying on my holey memory). The C specification says
766 A pointer to a function of one type may be converted to a pointer to a function of another type and back again;
767 the result shall compare equal to the original pointer.
768 If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
and GCC 4.2 prereleases (this was settled way before 4.3) was following these rules: the cast of a function pointer did not result in NULL, as I wrote, but attempting to call a function through a incompatible type, i.e.
func = (cb_t)nothing;
func(1);
from your example, would result in an abort. They changed back to the 4.1 behavior (allow but warn), partly because this change broke OpenSSL, but OpenSSL has been fixed in the meantime, and this is undefined behavior which the compiler is free to change at any time.
OpenSSL was only casting functions pointers to other function types taking and returning the same number of values of the same exact sizes, and this (assuming you're not dealing with floating-point) happens to be safe across all the platforms and calling conventions I know of. However, anything else is potentially unsafe.
I suspect you will get an undefined behaviour.
You can assign (with the proper cast) a pointer to function to another pointer to function with a different signature, but when you call it weird things may happen.
Your nothing() function takes no arguments, to the compiler this may mean that he can optimize the usage of the stack as there will be no arguments there. But here you call it with an argument, that is an unexpected situation and it may crash.
I can't find the proper point in the standard but I remember it says that you can cast function pointers but when you call the resulting function you have to do with the right prototype otherwise the behaviour is undefined.
As a side note, you should not compare a function pointer with a data pointer (like NULL) as thee pointers may belong to separate address spaces. There's an appendix in the C99 standard that allows this specific case but I don't think it's widely implemented. That said, on architecture where there is only one address space casting a function pointer to a data pointer or comparing it with NULL, will usually work.
You do run the risk of causing stack corruption. Having said that, if you declare the functions with extern "C" linkage (and/or __cdecl depending on your compiler), you may be able to get away with this. It would be similar then to the way a function such as printf() can take a variable number of arguments at the caller's discretion.
Whether this works or not in your current situation may also depend on the exact compiler options you are using. If you're using MSVC, then debug vs. release compile options may make a big difference.
It should be fine. Since the caller is responsible for cleaning up the stack after a call, it shouldn't leave anything extra on the stack. The callee (nothing() in this case) is ok since it wont try to use any parameters on the stack.
EDIT: this does assume cdecl calling conventions, which is usually the default for C.
As long as you can guarantee that you're making a call using a method that has the caller balance the stack rather than the callee (__cdecl). If you don't have a calling convention specified the global convention could be set to something else. (__stdcall or __fastcall) Both of which could lead to stack corruption.
This won't work unless you use implementation-specific/platform-specific stuff to force the correct calling convention. For some calling conventions the called function is responsible for cleaning up the stack, so they must know what's been pushed on.
I'd go for the check for NULL then call - I can't imagine it would have any impact on performance.
Computers can check for NULL about as fast as anything they do.
Casting a function pointer to NULL is explicitly not supported by the C standard. You're at the mercy of the compiler writer. It works OK on a lot of compilers.
It is one of the great annoyances of C that there is no equivalent of NULL or void* for function pointers.
If you really want your code to be bulletproof, you can declare your own nulls, but you need one for each function type. For example,
void void_int_NULL(int n) { (void)n; abort(); }
and then you can test
if (my_thing->func_a != void_int_NULL) my_thing->func_a(99);
Ugly, innit?

Resources