0

I need to call a function where I have the LPVOID and the number of arguments. Furthermore I know the types and positions of the arguments. The arguments can be of type int, int*, double, double*, string, string*. As the arguments can be in any order the possible list of templates would be very large. The return value is always boolean.

bool Func1(int);
bool Func1(int*);
bool Func1(double);
(...)
bool Func2(int,int);
bool Func2(int,int*);
(...)

So this is not an option. I've tried to use std::tuple but with no success. The following examples only works for a function with arguments (int, double).

    template <typename R, typename... Args>
    R call(FARPROC fp, Args... args) throw(HRESULT)
    {
        typedef R(__stdcall * function_pointer)(Args...);
        function_pointer P = (function_pointer)fp;
        const auto return_value = (*P)(std::forward<Args>(args)...);
        ().do_cast(fetch_back(args))...);
        return return_value;
     }

(...)
LPVOID function;
int iVal1 = 2;
double dbVal1 = 3.0;
auto t = std::make_tuple(iVal1 , dbVal1);
bool bRes = call<bool>((FARPROC)function, std::get<0>(t), std::get<1>(t));

What I am thinking about is a generic way of creating the std::tuple based on some input (string etc.), something like: auto t = create_tuple("int,int*,int").

4
  • You know that tuple is also templated on its types, right? You probably wouldn't be able to circumvent the issue of code size with it. Commented Jun 14, 2017 at 16:16
  • Also, if you say input string, do you mean compile time or runtime input? Commented Jun 14, 2017 at 16:18
  • 1
    What is LPVOID, can you explain? Edit: is it basically void*? Commented Jun 14, 2017 at 17:59
  • At any rate I think your "code bloat" concern is unfounded. The typedef and the cast that you have in the function body don't generate any code. All that the function body really does is call the passed function pointer, which is the work you need to do anyhow. In practice what you will probably see is that call always gets inlined (because a particular template sequence only shows up once) and is just a handful of extra lines of assembly, which you needed anyhow! Commented Jun 14, 2017 at 18:05

2 Answers 2

0

I have a proposal but you must set double variables through its address, like a pointer, because a double variable has 8 bytes meanwhile void pointer's size has 4 bytes for x86 and 8 bytes for x64. Also string variables must be setted as pointers:

#include "stdafx.h"
#include <string>

using namespace std;

bool Func1(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
{
    bool result = false;

    int a1 = (int)arg1;
    int a2 = *(int*)arg2;
    double a3 = *(double*)arg3;
    double* a4 = (double*)arg4;
    string a5 = *(string*)arg5;
    string* a6 = (string*)arg6;

    //Do something...

    return result;
}

int main()
{
    bool(*myFun)(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);
    myFun = &Func1;
    int a1 = 2;
    int a2 = 3;
    double a3 = 4;
    double* a4 = new double(5);
    string a5= "MyData 1";
    string* a6 = new string("MyData 2");

    bool r = (*myFun)((void*)a1, (void*)&a2, (void*)&a3, (void*)a4, (void*)&a5, (void*)a6);
    return 0;
}

enter image description here

I hope this could help you.

Sign up to request clarification or add additional context in comments.

1 Comment

This looks good, but unfortunately I am not able to change the called funtions as they are part of an existing library. I think it should be possible to do this via templates, but I have tried several ideas without success...
0

My suggestion, for anyone interested in alternatives...

Bury the LPVOID function under a meaningful API and never use it directly again.

Obviously, an LPVOID function taking a bunch of void *ters is not self-documenting, so provide something that is.

Provide various constructors or helper methods that accept the values required for making a specific low level call to the LPVOID and provide conversion methods for handing the values down to the LPVOID.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.