Wednesday 21 August 2019

c++ - C Pass arguments as void-pointer-list to imported function from LoadLibrary()



The problem I have is that I want to create a generic command line application that can be used to load a library DLL and then call a function in the library DLL. The function name is specified on the command line with the arguments also provided on the utility command line.



I can access the external function from a DLL dynamically loaded using the LoadLibrary() function. Once the library is loaded I can obtain a pointer to the function using GetProcAddress() I want to call the function with the arguments specified on the command line.




Can I pass a void-pointer-list to the function-pointer which I got returned by the LoadLibrary() function similar to the example below?



To keep the example code simple, I deleted the error-checking. Is there a way to get something like this working:




//Somewhere in another dll
int DoStuff(int a, int b)
{
return a + b;
}




int main(int argc, char **argv)
{
void *retval;
void *list = argv[3];
HMODULE dll;
void* (*generic_function)(void*);


dll = LoadLibraryA(argv[1]);

//argv[2] = "DoStuff"
generic_function = GetProcAddress(dll, argv[2]);

//argv[3] = 4, argv[4] = 7, argv[5] = NULL
retval = generic_function(list);
}



If I forgot to mention necessary information, please let me know.
Thanks in advance


Answer



You need to cast the function pointer returned by LoadLibrary to one with the right argument types before calling it. One way to manage it is to have a number call-adaptor functions that do the right thing for every possible function type you might want to call:



void Call_II(void (*fn_)(), char **args) {
void (*fn)(int, int) = (void (*)(int, int))fn_;
fn(atoi(args[0]), atoi(args[1]));
}
void Call_IS(void (*fn_)(), char **args) {

void (*fn)(int, char *) = (void (*)(int, char *))fn_;
fn(atoi(args[0]), args[1]);
}
...various more functions


Then you take the pointer you got from GetProcAddress and the additional arguments and pass them to the correct Call_X function:



void* (*generic_function)();


dll = LoadLibraryA(argv[1]);

//argv[2] = "DoStuff"
generic_function = GetProcAddress(dll, argv[2]);

//argv[3] = 4, argv[4] = 7, argv[5] = NULL

Call_II(generic_function, &argv[3]);



The problem is that you need to know what the type of the function you're getting the pointer for is and call the appropriate adaptor function. Which generally means making a table of function name/adaptors and doing a lookup in it.



The related problem is that there's no function analogous to GetProcAddress that will tell you the argument types for a function in the library -- that information simply isn't stored anywhere accessable in the dll.


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...