I want to implement a function like a c++ generic. Apart from integers, the parameters should also support char type, and any other types as well.
void function t(int a[],int len);
How to implement this in C language?
Since you don't have templates in C like you do C++ you have a few different options, which may be suitable depending on the task at hand:
Using the pre-processor and creating a basic macro, such as your basic MIN/MAX type macro that simply wraps a few < and > operations.
Writing different versions of the function for specific data types - function_int(int...), function_char(char...), etc.
Writing a generic function which takes in data as a void*, not knowing the implementation details, and a function pointer which is called by the function which acts on the data and does know how to operate on this data.
In this case, look at a function like bsearch, where the search key and array are of type void *, and a comparison function is passed for a specific type of data:
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
The comparison function is the only piece of code that needs to know the type of the data, so you only need to write the generic part of your function once. However, you do still need to write a function for each data type that you want to operate on, as with the point above.
This is a technique that I believe was described in the book C Unleashed. The book probably has something a little more elegant than what I am able to reproduce from memory.
You can have an include file like this:
/* function.tmpl */
#ifndef FUNCTION
#define FUNCTION_PASTE(X,Y) X ## _ ## Y
#define FUNCTION(X) FUNCTION_PASTE(function, X)
#endif
void FUNCTION(TYPE) (TYPE a[], int len) {
/* do something */
}
Then you can include it like this:
#define TYPE int
#include "function.tmpl"
#undef TYPE
#define TYPE double
#include "function.tmpl"
#undef TYPE
And call functions like this:
int a[4];
FUNCTION(int)(a, 4);
double b[5];
FUNCTION(double)(b, 5);
The idiomatic way to do this in C is to pass a void*. But then you need an extra information to actually do anything with it.
You could try something like this:
enum data_type { CHAR_TYPE, INT_TYPE };
void function t(void* buf, size_t len, enum data_type type) {
int* int_ary;
char* char_ary;
if (type == CHAR_TYPE) {
char_ary* = buf;
...
} else if (type == INT_TYPE) {
int_ary* = buf;
...
}
}
It's hackish and error-prone, but it could work. It's not exactly like C++ in that it's one unified function instead of a separate version for each type.
Related
I intend to sort an array of multidimentional points each time by another coordinate.
I want to use c qsort() method but in order to do so I have to use comparator function which its input is only two pointers, so I can't send it the desired coordinate to sort by.
Therefore I figured out two solutions and I am struggling choosing the best one of them :
Use a static variable - an int in this example - initialize it to a -1, and before calling the qsort function set it to the wanted coordinate. In addition, make my comparator, access this variable and compare based on it.
Build a new struct to hold a pointer to the point and the desired coordinate, then make the comparator to sort two pointers to such struct and use the additional info from the struct.
The first sounds like a quick solution though it might be loop hole, while the second sounds like an overkill for such a simple task.
I would be glad to hear any better solution if there is to the problem.
If your system has qsort_r, you can use that. qsort_r has an extra parameter that you can use to pass your coordinate in.
int comparator(const void *l, const void *r, void *param)
{
Point* lPoint = (Point*) l;
Point* rPoint = (Point*) r;
Coordinate* coord = (Coordinate*) param;
// Do your comparison ....
}
void mySort(Point* list, size_t listSize, Coordinate sortCoord)
{
qsort_r(list, listSize, sizeof(Point), comparator, &sortCoord);
}
It's definitely available if you are using glibc (e.g. on Linux) and on OS X. However, it is not officially portable. See this answer on portability
How portable is the re-entrant qsort_r function compared to qsort?
My code example is written for the Linux version. With OS X, the comparator must be declared as
int comparator( void *param, const void *l, const void *r)
and the qsort_r call is
qsort_r(list, listSize, sizeof(Point), &sortCoord, comparator);
The most portable version would probably indeed be to encapsulate the comparsion object(s) ("functors") in a separate file, then use a static file scope variable to change the behavior of the function.
something.h
void set_something (something_t s);
int compare_something (const void* obj1, const void* obj2);
something.c
#include "something.h"
static something_t someting = 0;
void set_something (something_t s)
{
something = s;
}
int compare_something (const void* obj1, const void* obj2)
{
const coord_t* c1 = obj1;
const coord_t* c2 = obj2;
// do stuff with c1, c2 based on something
}
The only down-side with this is that you can't have multiple threads performing different kinds of sorting at the same time, but that's not likely to be an issue. (If it is, design some way to pass a "something" variable as parameter to each thread callback instead.)
I suggest an option #3
C11 presents qsort_s() which provides the needed context parameter. This is in Annex K (normative) and so may not be included in C11 compliant compiler.
The availability of this function may not be wide.
K.3.6.3.2 The qsort_s function
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y,
void *context), void *context);
... The third argument to the comparison function is the
context argument passed to qsort_s. The sole use of context by qsort_s is to pass it to the comparison function
If this function is not available, consider an alternative that mimics this interface.
This idea is similar to the #JeremyP which suggest qsort_r. The two functions are similar, except for argument order amongst qsort_r() variants the return type.
I am making C dynamic array library, kind of. Note that I'm doing it for fun in my free time, so please do not recommend million of existing libraries.
I started implementing sorting. The array is of arbitrary element size, defined as struct:
typedef struct {
//[PRIVATE] Pointer to array data
void *array;
//[READONLY] How many elements are in array
size_t length;
//[PRIVATE] How many elements can further fit in array (allocated memory)
size_t size;
//[PRIVATE] Bytes per element
size_t elm_size;
} Array;
I originally prepared this to start with the sort function:
/** sorts the array using provided comparator method
* if metod not provided, memcmp is used
* Comparator signature
* int my_comparator ( const void * ptr1, const void * ptr2, size_t type_size );
**/
void array_sort(Array* a, int(*comparator)(const void*, const void*, size_t)) {
if(comparator == NULL)
comparator = &memcmp;
// Sorting algorithm should follow
}
However I learned about qsort:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
Apparently, I could just pass my internal array to qsort. I could just call that:
qsort (a->array, a->length, a->elm_size, comparator_callback);
But there's a catch - qsort's comparator signature reads as:
int (*compar)(const void*,const void*)
While memcmp's signature is:
int memcmp ( const void * ptr1, const void * ptr2, size_t type_size );
The element size is missing in qsort's callback, meaning I can no longer have a generic comparator function when NULL is passed as callback. I could manually generate comparators up to X bytes of element size, but that sounds ugly.
Can I use qsort (or other sorting built-in) along with memcpy? Or do I have to chose between built-in comparator and built-in sorting function?
C11 provides you with an (admittedly optional) qsort_s function, which is intended to deal with this specific situation. It allows you to pass-through a user-provided void * value - a context pointer - from the calling code to the comparator function. The comparator callback in this case has the following signature
int (*compar)(const void *x, const void *y, void *context)
In the simplest case you can pass a pointer to the size value as context
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdlib.h>
...
int comparator_callback(const void *x, const void *y, void *context)
{
size_t elm_size = *(const size_t *) context;
return memcmp(x, y, elm_size);
}
...
qsort_s(a->array, a->length, a->elm_size, comparator_callback, &a->elm_size);
Or it might make sense to pass a pointer to your entire array object as context.
Some *nix-based implementations have been providing a similar qsort_r function for a while, although it is non-standard.
A non-thread-safe way is use private global variable to pass the size.
static size_t compareSize = 0;
int defaultComparator(const void *p1, const void *p2) {
return memcmp(p1, p2, compareSize);
}
void array_sort(Array* a, int(*comparator)(const void*, const void*, size_t)) {
if(comparator == NULL) {
compareSize = a->elm_size;
comparator = &defaultComparator;
}
// Sorting algorithm should follow
}
You can make it thread-safe by make compareSize thread-local variable (__thread)
The qsort() API is a legacy of simpler times. There should be an extra "environment" pointer passed unaltered from the qsort() call to each comparison. That would allow you to pass the object size and any other necessary context in a thread safe manner.
But it's not there. #BryanChen's method is the only reasonable one.
The main reason I'm writing this answer is to point out that there are very few cases where memcmp will do something useful. There are not many kinds of objects where comparison by lexicographic order of constituent unsigned chars makes any sense.
Certainly comparing structs that way is dangerous because padding byte values are unspecified. Even the equality part of the comparison can fail. In other words,
struct foo { int i; };
void bar(void) {
struct foo a, b;
a.i = b.i = 0;
if (memcmp(&a, &b, sizeof a) == 0) printf("equal!");
}
may - by the C standard - print nothing!
Another example: for something as simple as unsigned ints, you'll get different sort orders for big- vs. little-endian storage order.
unsigned a = 0x0102;
unsigned b = 0x0201;
printf("%s", memcmp(&a, &b, sizeof a) < 0 ? "Less!" : "More!");
will print Less or More depending on the machine where it's running.
Indeed the only object type I can imagine that makes sense to compare with memcmp is equal-sized blocks of unsigned bytes. This isn't a very common use case for sorting.
In all, a library that offers memcmp as a comparison function is doomed to be error prone. Someone will try to use it as a substitute for a specialized comparison that's really the only way to obtain the desired result.
I have an incr function to increment the value by 1
I want to make it generic,because I don't want to make different functions for the same functionality.
Suppose I want to increment int,float,char by 1
void incr(void *vp)
{
(*vp)++;
}
But the problem I know is Dereferencing a void pointer is undefined behaviour. Sometimes It may give error :Invalid use of void expression.
My main funciton is :
int main()
{
int i=5;
float f=5.6f;
char c='a';
incr(&i);
incr(&f);
incr(&c);
return 0;
}
The problem is how to solve this ? Is there a way to solve it in Conly
or
will I have to define incr() for each datatypes ? if yes, then what's the use of void *
Same problem with the swap() and sort() .I want to swap and sort all kinds of data types with same function.
You can implement the first as a macro:
#define incr(x) (++(x))
Of course, this can have unpleasant side effects if you're not careful. It's about the only method C provides for applying the same operation to any of a variety of types though. In particular, since the macro is implemented using text substitution, by the time the compiler sees it, you just have the literal code ++whatever;, and it can apply ++ properly for the type of item you've provided. With a pointer to void, you don't know much (if anything) about the actual type, so you can't do much direct manipulation on that data).
void * is normally used when the function in question doesn't really need to know the exact type of the data involved. In some cases (e.g., qsort) it uses a callback function to avoid having to know any details of the data.
Since it does both sort and swap, let's look at qsort in a little more detail. Its signature is:
void qsort(void *base, size_t nmemb, size_t size,
int(*cmp)(void const *, void const *));
So, the first is the void * you asked about -- a pointer to the data to be sorted. The second tells qsort the number of elements in the array. The third, the size of each element in the array. The last is a pointer to a function that can compare individual items, so qsort doesn't need to know how to do that. For example, somewhere inside qsort will be some code something like:
// if (base[j] < base[i]) ...
if (cmp((char *)base+i, (char *)base+j) == -1)
Likewise, to swap two items, it'll normally have a local array for temporary storage. It'll then copy bytes from array[i] to its temp, then from array[j] to array[i] and finally from temp to array[j]:
char temp[size];
memcpy(temp, (char *)base+i, size); // temp = base[i]
memcpy((char *)base+i, (char *)base+j, size); // base[i] = base[j]
memcpy((char *)base+j, temp, size); // base[j] = temp
Using void * will not give you polymorphic behavior, which is what I think you're looking for. void * simply allows you to bypass the type-checking of heap variables. To achieve actual polymorphic behavior, you will have to pass in the type information as another variable and check for it in your incr function, then casting the pointer to the desired type OR by passing in any operations on your data as function pointers (others have mentioned qsort as an example). C does not have automatic polymorphism built in to the language, so it would be on you to simulate it. Behind the scenes, languages that build in polymorphism are doing something just like this behind the scenes.
To elaborate, void * is a pointer to a generic block of memory, which could be anything: an int, float, string, etc. The length of the block of memory isn't even stored in the pointer, let alone the type of the data. Remember that internally, all data are bits and bytes, and types are really just markers for how the logical data are physically encoded, because intrinsically, bits and bytes are typeless. In C, this information is not stored with variables, so you have to provide it to the compiler yourself, so that it knows whether to apply operations to treat the bit sequences as 2's complement integers, IEEE 754 double-precision floating point, ASCII character data, functions, etc.; these are all specific standards of formats and operations for different types of data. When you cast a void * to a pointer to a specific type, you as the programmer are asserting that the data pointed to actually is of the type you're casting it to. Otherwise, you're probably in for weird behavior.
So what is void * good for? It's good for dealing with blocks of data without regards to type. This is necessary for things like memory allocation, copying, file operations, and passing pointers-to-functions. In almost all cases though, a C programmer abstracts from this low-level representation as much as possible by structuring their data with types, which have built-in operations; or using structs, with operations on these structs defined by the programmer as functions.
You may want to check out the Wikipedia explanation for more info.
You can't do exactly what you're asking - operators like increment need to work with a specific type. So, you could do something like this:
enum type {
TYPE_CHAR,
TYPE_INT,
TYPE_FLOAT
};
void incr(enum type t, void *vp)
{
switch (t) {
case TYPE_CHAR:
(*(char *)vp)++;
break;
case TYPE_INT:
(*(int *)vp)++;
break;
case TYPE_FLOAT:
(*(float *)vp)++;
break;
}
}
Then you'd call it like:
int i=5;
float f=5.6f;
char c='a';
incr(TYPE_INT, &i);
incr(TYPE_FLOAT, &f);
incr(TYPE_CHAR, &c);
Of course, this doesn't really give you anything over just defining separate incr_int(), incr_float() and incr_char() functions - this isn't the purpose of void *.
The purpose of void * is realised when the algorithm you're writing doesn't care about the real type of the objects. A good example is the standard sorting function qsort(), which is declared as:
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
This can be used to sort arrays of any type of object - the caller just needs to supply a comparison function that can compare two objects.
Both your swap() and sort() functions fall into this category. swap() is even easier - the algorithm doesn't need to know anything other than the size of the objects to swap them:
void swap(void *a, void *b, size_t size)
{
unsigned char *ap = a;
unsigned char *bp = b;
size_t i;
for (i = 0; i < size; i++) {
unsigned char tmp = ap[i];
ap[i] = bp[i];
bp[i] = tmp;
}
}
Now given any array you can swap two items in that array:
int ai[];
double ad[];
swap(&ai[x], &ai[y], sizeof(int));
swap(&di[x], &di[y], sizeof(double));
Example for using "Generic" swap.
This code swaps two blocks of memory.
void memswap_arr(void* p1, void* p2, size_t size)
{
size_t i;
char* pc1= (char*)p1;
char* pc2= (char*)p2;
char ch;
for (i= 0; i<size; ++i) {
ch= pc1[i];
pc1[i]= pc2[i];
pc2[i]= ch;
}
}
And you call it like this:
int main() {
int i1,i2;
double d1,d2;
i1= 10; i2= 20;
d1= 1.12; d2= 2.23;
memswap_arr(&i1,&i2,sizeof(int)); //I use memswap_arr to swap two integers
printf("i1==%d i2==%d \n",i1,i2); //I use the SAME function to swap two doubles
memswap_arr(&d1,&d2,sizeof(double));
printf("d1==%f d2==%f \n",d1,d2);
return 0;
}
I think that this should give you an idea of how to use one function for different data types.
Sorry if this may come off as a non-answer to the broad question "How to make generic function using void * in c?".. but the problems you seem to have (incrementing a variable of an arbitrary type, and swapping 2 variables of unknown types) can be much easier done with macros than functions and pointers to void.
Incrementing's simple enough:
#define increment(x) ((x)++)
For swapping, I'd do something like this:
#define swap(x, y) \
({ \
typeof(x) tmp = (x); \
(x) = (y); \
(y) = tmp; \
})
...which works for ints, doubles and char pointers (strings), based on my testing.
Whilst the incrementing macro should be pretty safe, the swap macro relies on the typeof() operator, which is a GCC/clang extension, NOT part of standard C (tho if you only really ever compile with gcc or clang, this shouldn't be too much of a problem).
I know that kind of dodged the original question; but hopefully it still solves your original problems.
You can use the type-generic facilities (C11 standard). If you intend to use more advanced math functions (more advanced than the ++ operator), you can go to <tgmath.h>, which is type-generic definitions of the functions in <math.h> and <complex.h>.
You can also use the _Generic keyword to define a type-generic function as a macro. Below an example:
#include <stdio.h>
#define add1(x) _Generic((x), int: ++(x), float: ++(x), char: ++(x), default: ++(x))
int main(){
int i = 0;
float f = 0;
char c = 0;
add1(i);
add1(f);
add1(c);
printf("i = %d\tf = %g\tc = %d", i, f, c);
}
You can find more information on the language standard and more soffisticated examples in this post from Rob's programming blog.
As for the * void, swap and sort questions, better refer to Jerry Coffin's answer.
You should cast your pointer to concrete type before dereferencing it. So you should also add code to pass what is the type of pointer variable.
Lets take qsort()'s comparison callback function as an example
int (*compar)(const void *, const void *)
What happens when the result of the comparison function depends on the current value of a variable? It appears my only two options are to use a global var (yuck) or to wrap each element of the unsorted array in a struct that contains the additional information (double yuck).
With qsort() being a standard function, I'm quite surprised that it does not allow for additional information to be passed in; something along the lines of execv()'s NULL-terminated char *const argv[] argument.
The same thing can be applied to other functions which define a callback that leave no headroom for additional parameters, ftw() & nftw() being two others I've had this problem with.
Am I just "doing it wrong" or is this a common problem and chalked up to an oversight with these types of callback function definitions?
EDIT
I've seen a few answers which say to create multiple callback functions and determine which one is appropriate to pass to qsort(). I understand this method in theory, but how would you apply it in practice if say I wanted the comparison callback function to sort an array of ints depending on how close the element is to a variable 'x'?. It would appear that I would need one callback function for each possible value of 'x' which is a non-starter.
Here is a working example using the global variable 'x'. How would you suggest I do this via multiple callback functions?
#include <stdint.h>
#include <stdio.h>
#include <math.h>
int bin_cmp(const void*, const void*);
int x;
int main(void)
{
int i;
int bins[6] = { 140, 100, 180, 80, 240, 120 };
x = 150;
qsort(bins, 6, sizeof(int), bin_cmp);
for(i=0; i < 6; i++)
printf("%d ", bins[i]);
return 0;
}
int bin_cmp(const void* a, const void* b)
{
int a_delta = abs(*(int*)a - x);
int b_delta = abs(*(int*)b - x);
if ( a_delta == b_delta )
return 0;
return a_delta < b_delta ? -1 : 1;
}
Output
140 180 120 100 80 240
Change the value of the function pointer. The whole point (no pun intended) of function pointers is that the user can pass in different functions under different circumstances. Rather that passing in a single function which acts differently based on external circumstances, pass in different functions based on the external circumstances.
This way, you only need to know about the values of variables in the context of the call to qsort() (or whatever function you're using), and write a couple different simpler comparison functions instead of one big one.
In response to your edit
To deal with the issue described in your update, just use to the global variable by name in your comparison function. This will certainly work if you are storing the variable at the global scope, and I believe qsort() will be able to find it at most other (public) scopes visible to the comparison function definition, as long as the scope is fully qualified.
However, this approach won't work if you want to pass a value straight into the sorting process without putting it in a variable.
It sounds like you need the bsearch_s() and qsort_s() functions defined by TR 24731-1:
§6.6.3.1 The bsearch_s function
Synopsis
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdlib.h>
void *bsearch_s(const void *key, const void *base,
rsize_t nmemb, rsize_t size,
int (*compar)(const void *k, const void *y, void *context),
void *context);
§6.6.3.2 The qsort_s function
Synopsis
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdlib.h>
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);
Note that the interface has the context that you need.
Something rather close to this should be available in the MS Visual Studio system.
With qsort's signature being what it is, I think your options are pretty limited. You can use a global variable or wrap your elements in structs as you suggested, but I'm not aware of any good "clean" way of doing this in C. I imagine there are other solutions out there, but they won't be any cleaner than using global variables. If your application is single-threaded, I would say this is your best bet as long as you're careful with the globals.
I'd listen to tlayton, and wrap that logic in a function that returns a pointer to the appropriate comparison function.
You can write your own specialized qsort implementation and customize it to your need.
To give you an idea about how short it is, this is a qsort implementation with your delta.
void swap(int *a, int *b)
{
int t=*a; *a=*b; *b=t;
}
void yourQsort(int arr[], int beg, int end, int delta)
{
if (end > beg + 1)
{
int piv = arr[beg], l = beg + 1, r = end;
while (l < r)
{
//Here use your var something like this
int a_delta = abs(arr[l] - delta);
int b_delta = abs(piv - delta);
if (a_delta <= delta)
l++;
else
swap(&arr[l], &arr[--r]);
}
swap(&arr[--l], &arr[beg]);
yourQsort(arr, beg, l, delta);
yourQsort(arr, r, end, delta);
}
}
More C-optimized implementations are said to be here.
You will have to prepare several function callbacks and check the value before running qsort, then send the correct one.
IMO, go with the global. The problem is that you're really asking qsort to do two things, both sort and map, where it's only designed to do the first.
The other thing you could do is break it down into a couple steps. First compute an array of these (one for each element of the source array):
struct sort_element {
int delta; // This is the delta value
int index; // This is the index of the value in the source array
}
Call qsort on that array, using a sort function that compares delta values. Then you use the index'es on the sorted array to order your original array. This consumes some memory, but it may not matter that much. (Memory is cheap, and the only thing you have to store in the temporary array is the key, not the entire value.)
I've declared many functions in one driver, and am passing the pointers to the functions to another driver in a list with the node format:
struct node
{
char def_prototype[256]; //example:(int (*)(wchar, int, int))
void *def_function;
};
Is there a way to typecast def_function to the prototype given in def_prototype?
Currently I'm using simple switch and strcmp, but I wanted to generalize it if possible.
PS: I know that casting between void pointer and function pointer is unsafe (as mentioned in various places in SO), but desperate times call for desperate measures and I have taken lot of care.
EDIT:
Sorry for the lack in clarity. I want to actually call the function (not just cast it), making a function pointer at runtime based on the char[] provided.
EDIT AGAIN:
Since I'm working at the kernel level (windows driver), I don't have access to much resources, so, I'm sticking to my current implementation (with some changes to kill back-doors). Thanks to all for your help.
ISO-C does not allow casting between function and data pointers, ie you should use a void (*)(void) instead of a void * to hold your function.
That aside, YeenFei is correct in his assertion that there is no general platform-independant solution, meaning the best you can do in C itself is to supply a list of supported signatures.
You should implement your own encoding scheme instead of using plain C prototypes. It's common to use a string where each char represents a function argument (and the first one the return value); a function of type int (*)(wchar, int, int) for example could have the signature "iwii".
Signature lookup tables can then be easily built using bsearch() and strcmp(); here's a complete example:
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmp(const void *key, const void *element)
{
return strcmp(key, *(const char * const *)element);
}
static _Bool dispatch(const char *sig, void (*func)(void), void *retval, ...)
{
// supported signatures; must be ordered according to strcmp()
static const char * const SIGS[] = { "iii", "v", "vi" };
const char * const *match = bsearch(
sig, SIGS, sizeof SIGS / sizeof *SIGS, sizeof *SIGS, cmp);
if(!match) return 0;
va_list args;
va_start(args, retval);
switch(match - SIGS)
{
case 0: { // iii
int a1 = va_arg(args, int);
int a2 = va_arg(args, int);
int rv = ((int (*)(int, int))func)(a1, a2);
if(retval) memcpy(retval, &rv, sizeof rv);
break;
}
case 1: { // v
func();
break;
}
case 2: { // vi
int a1 = va_arg(args, int);
((void (*)(int))func)(a1);
break;
}
default:
assert(!"PANIC");
}
va_end(args);
return 1;
}
// example code:
static int add(int a, int b)
{
return a + b;
}
int main(void)
{
int sum;
dispatch("iii", (void (*)(void))add, &sum, 3, 4);
printf("%i", sum);
return 0;
}
unless you want to mess with assembly thunking (pushing data onto stack before jumping, etc), there is better way other than doing some switch case.
if the destination function is finite and known, why not create a lookup table (map<string, functor>) for it ?
A good implementation of similar ideas is libffi. This implements the gory details of declaring and calling functions with arbitrary calling conventions and signatures. It is (surprisingly) platform portable, and known to work on Linux and Windows out of the box.
An example of its use is the Lua extension library alien. That demonstrates calling arbitrary functions declared at runtime and adapting from native Lua types to the types required for the calling conventions. The specific Lua binding won't be useful to you, but it serves as a complete working example of how and why one might actually use libffi.
Since C has no runtime type information, there is absolutely no need to do a dynamic cast as you are considering. Just pass the pointer and if everything fits, it will work. If the pointer doesn't point to a function with the right signature, there is no way to fix it.
There are basically two solutions:
Go to the assembly level and parse the prototype string there and put the arguments you find in the prototype there where the other function will expect them.
Make a long list of all supported prototypes and compare the current one with the list. When you find a match, you can make the typecast as needed. The most common structure for this test would ba an if-else ladder.