I'm writing an interface layer to a shared library we are opening via dlopen/dlsym. The parameters to the functions may change depending on whether the library is compiled for system A vs system B.
I had a thought that instead of doing a bunch of typedefs, I could try to create an array of all of the function pointers returned from dlsym and then eventually use VA_ARGS to pass in the data. This would also allow me to deal with extensibility-- if the library parameters change, we'd just need to update the calling functions, instead of the typedefs below, too. Basically, I'm looking to change something like this:
typedef int* (*foo_t)(int, int);
typedef int* (*bar_t)(int, int, char*, int);
typedef void (*baz_t)(void);
void GetStuff()
{
void *handle = dlopen("/my/cool/libLibrary.so", RTLD_LAZY);
foo_t foo = dlsym(handle, "TheFooFunction");
bar_t bar = dlsym(handle, "TheBarFunction");
baz_t baz = dlsym(handle, "TheBazFunction");
foo(1, 2);
bar(3, 4, "cool", 5);
baz();
}
into this:
enum funcs
{
FUNC_FOO = 0,
FUNC_BAR = 1,
FUNC_BAZ = 2,
FUNC_MAX
};
void funcArray[FUNC_MAX]; // Not legal - looking for a way to do something like this...
char *functionNames[FUNC_MAX] =
{
[FUNC_FOO] = "TheFooFunction",
[FUNC_BAR] = "TheBarFunction",
[FUNC_BAZ] = "TheBazFunction"
};
void GetStuff()
{
void *handle = dlopen("/my/cool/libLibrary.so", RTLD_LAZY);
for (int i = 0; i < FUNC_MAX; i++)
{
funcArray[i] = dlsym(handle, functionNames[i]);
}
funcArray[FUNC_FOO](1, 2);
funcArray[FUNC_BAR](3, 4, "cool", 5);
funcArray[FUNC_BAZ]();
}
Is this possible? I know the array of voids is illegal. I can't use uintptr_t in it's place, since those are for data (not function) pointers. Are there any other options other than creating big #define's for each configuration and doing it the original way?
VA_ARGS. Are you thinking of the__VA_ARGS__preproessor feature or theva_argvariable-argument-list feature? What role do you envision it playing?void *—except that any function-pointer type may serve as a universal function pointer type. All pointer-to-function types may be converted to other pointer-to-function types, and converting back to the original type produces the original pointer (or equivalent). So you can use an array of any function-pointer type of your choosing and manage the pointers with casts. The real question is how you intend to use those pointers—how will you call the functions with the correct arguments.