Markuse
Markuse

Reputation: 17

calling a function via LPVOID with up to 10 arguments of different types

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").

Upvotes: 0

Views: 1168

Answers (2)

Rodney P. Barbati
Rodney P. Barbati

Reputation: 2090

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.

Upvotes: 0

Jorge Omar Medra
Jorge Omar Medra

Reputation: 988

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.

Upvotes: 0

Related Questions