Creating a function list

Hello,
I'm trying to create a lsit of functions. Here's what I want to do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// main.cpp
#include <iostream>
#include "function_list.hpp"
using namespace std;


void add_int(int a, int b,int &ret)
{
  ret= a+b;
}
void add_float(float a,float b, float &ret)
{
  ret=a+b;
}


int main()
{
FunctionList fl;

int ret_int;
float ret_float;

// Add functions to list
fl.AddFunction("add_int",add,10,20,ret_int);
fl.AddFunction("add_float",add,3.14,20.5,ret_float);

// Execute functions
fl.Execute(0);
fl.Execute(1);

// Print out the results
cout <<"20+10=="<<re_int<<endl;
cout <<"3.14+20.5=="<<ret_float<<endl;

    return 0;
}


But I'm completely stuck in implementation of FunctionList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// function_list.hpp
#ifndef FUNCTION_LIST_HPP
#define FUNCTION_LIST_HPP

#include <string>
#include <vector>
#include <map>


typedef void*(*generic_pointer)(...); // There's no generic pointer in C++ (I think) but this is somewaht similar


class FunctionList
{
private:
  // function pointers
  typedef void (*fp_add_int)(int a, int b, int &ret);
  typedef void (*fp_add_float)(float a, float b, float &ret);

  std::map<std::string,generic_pointer > function_list; // List of known functions
  std::map<std::string,void*> call_list; // List of functions to be called

public:

  FunctionList();

  bool AddFunction(std::string function_name,...); // '...' are arguments to function
  void Execute(int function_number);


};


#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// function_list.cpp
#include "function_list.hpp"



FunctionList::FunctionList()
{

}


bool FunctionList::AddFunction(std::string function_name,...)
{

}

void FunctionList::Execute(int function_number)
{

}


Now the questions:
1. Where and how should I store function arguments? I'm thinking about vector but vector only stores elements of the same type while I will want to pass arguments of different types to function.
2. How to associate function name with function pointer and with its arguments ( maybe I can pass va_list generic_pointer or something?)
That's all for now.

Thanks for help.

You can do what you want with boost::bind and boost::function.

WARN: Uncompiled:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <vector>

void add_int( int a, int b, int& sum )
    { sum = a + b; }

void add_float( float a, float b, float& sum )
    { sum = a + b; }

int main()
{
   typedef boost::function< void() > Function;

   std::vector< Function > fn_list;
   int                                 ans1 = 0;
   float                              ans2 = 0.0;

   fn_list.push_back( boost::bind( &add_int, 10, 20, boost::ref( ans1 ) ) );
   fn_list.push_back( boost::bind( &add_float, 3.14, 2.17, boost::ref( ans2 ) ) );

   fn_list[ 0 ]();
   fn_list[ 1 ]();

   std::cout << "Answers are " << ans1 << " and " << ans2 << std::endl;
}
wow. I should really start using boost..
I tried to do this myself. floats don't work though. I wonder why..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cstring>

struct FUNCTION{
    void* func;
    char* arg;
    int arg_sz;

    void set(void* f, int arg_sz, ...);
    void execute();
};

void addd(double a, double b, double& c){
    c = a + b;
}

void addi(int a, int b, int& c){
    c = a + b;
}

void FUNCTION::set(void* f, int in_arg_sz, ...){
    func = f;
    char* ptr = (char*)(&in_arg_sz+1);
    arg_sz = in_arg_sz;
    arg = new char[arg_sz];
    memcpy(arg, ptr, arg_sz);
}

void FUNCTION::execute(){
    void* cptr;
    __asm{
        sub esp, dword ptr[arg_sz]
        mov dword ptr[cptr], esp
    }
    memcpy(cptr, arg, arg_sz);
    void* F = func;
    _asm{
        call dword ptr[F]
        add esp, dword ptr[arg_sz]
    }
}

int main(){
    double cd;
    int ci;
    FUNCTION fd, fi;
    fd.set(addd, 8+8+4, 5.0, 3.0, &cd);
    fi.set(addi, 4+4+4, 5, 3, &ci);

    fd.execute();
    fi.execute();
    return 0;
}
I'll try boost later if I won't figure this out myself.
Copy pasta from a header i wrote;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
   /*****************************************************************************************/
    /** class Functor                                                                       **/
    /** public:                                                                             **/
    /**  typedef void(*Function)();                                                         **/
    /**  typedef void* Param;                                                               **/
    /**  Functor(Function, unsigned, bool = false)                                          **/
    /**  void SetFunction(Function, unsigned, bool = false)                                 **/
    /**  void SetParam(Param, unsigned, unsigned)                                           **/
    /**  template<class rtype> rtype Call()                                                 **/
    /**  void Call()                                                                        **/
    /*****************************************************************************************/

    class Functor
    {
        public:
        typedef void(*Function)();
        typedef void* Param;
        private:
        Param* paramv;
        unsigned* params;
        unsigned paramc;
        Function func;
        bool stdcall;
        public:
        inline Functor()
        {
            paramv = 0;
        }
        Functor(Function fp, unsigned c, bool sc = false)
        {
            func = fp;
            stdcall = c;
            paramc = c;
            if(paramc > 0)
            {
                paramv = new void*[paramc];
                params = new unsigned[paramc];
            }
            for(int i = 0; i < paramc; i++)
            {
                paramv[i] = 0;
                params[i] = 0;
            }
        }
        inline ~Functor()
        {
            if(paramv)
            {
                delete[] paramv;
                delete[] params;
            }
        }
        void SetFunction(Function fp, unsigned c, bool sc = false)
        {
            func = fp;
            stdcall = sc;
            if(paramv != 0)
            {
                delete[] paramv;
                delete[] params;
            }
            paramc = c;
            if(paramc > 0)
            {
                paramv = new void*[paramc];
                params = new unsigned[paramc];
            }
        }
        void SetParam(Param var, unsigned size, unsigned i)
        {
            paramv[i] = var;
            params[i] = size;
        }
        template<class rtype>
        rtype Call()
        {
            rtype ret;
            if(func == 0)
                return ret;
            for(int i = paramc-1; i >= 0; i--)
            {
                if(params[i] ==  2)
                    asm("push %0" :: "r"(*(short*)paramv[i]));
                else if(params[i] ==  4)
                    asm("push %0" :: "r"(*(int*)paramv[i]));
                else if(params[i] ==  8)
                    asm("push %0" :: "r"(*(double*)paramv[i]));
                else if(params[i] == 12)
                    asm("push %0" :: "r"(*(long double*)paramv[i]));
            }
            ret = ((rtype(*)())func)();
            if(stdcall == false)
            for(int i = 0; i < paramc; i++)
            {
                if(params[i] ==  2)
                    asm("pop %0" :: "r"(*(short*)paramv[i]));
                else if(params[i] ==  4)
                    asm("pop %0" :: "r"(*(int*)paramv[i]));
                else if(params[i] ==  8)
                    asm("pop %0" :: "r"(*(double*)paramv[i]));
                else if(params[i] == 12)
                    asm("pop %0" :: "r"(*(long double*)paramv[i]));
            }
            return ret;
        }
        void Call()
        {
            if(func == 0)
                return;
            for(int i = paramc-1; i >= 0; i--)
            {
                if(params[i] ==  2)
                    asm("push %0" :: "r"(*(short*)paramv[i]));
                else if(params[i] ==  4)
                    asm("push %0" :: "r"(*(int*)paramv[i]));
                else if(params[i] ==  8)
                    asm("push %0" :: "r"(*(double*)paramv[i]));
                else if(params[i] == 12)
                    asm("push %0" :: "r"(*(long double*)paramv[i]));
            }
            func();
            if(stdcall == false)
            for(int i = 0; i < paramc; i++)
            {
                if(params[i] ==  2)
                    asm("pop %0" :: "r"(*(short*)paramv[i]));
                else if(params[i] ==  4)
                    asm("pop %0" :: "r"(*(int*)paramv[i]));
                else if(params[i] ==  8)
                    asm("pop %0" :: "r"(*(double*)paramv[i]));
                else if(params[i] == 12)
                    asm("pop %0" :: "r"(*(long double*)paramv[i]));
            }
        }
    };

Call any function with any arguements
Looks cool but I have few questions - how can I (or is it possible to) pass references to SetParam function?
And how to use template<class rtype> rtype Call() ?
Heres an easy example that should cover everything;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
    char* somedata1 = "Hello world, im %s";
    char* somedata2 = "Awesome"; //result of what were going to do should be obvious =P
    Functor MyFunc;
    //SetFunction parameter 1: the function, printf (Functor::Function is a function pointer type that returns nothing, takes nothing)
    //amount of arguements is 2(with printf you can specify any amount)
    //(set the third parameter to true if it uses __stdcall or "WINAPI", like most windows functions do, eg. MessageBox, its false by default)
    MyFunc.SetFunction((Functor::Function)printf, 2); //Functor::Function = void(*)()

    //Functor::Param is void*, you need to specify the size of the parameter type, and the parameter index
    MyFunc.SetParam((Functor::Param)&somedata1, sizeof(char*), 0); // printf(somedata1, ...);
    MyFunc.SetParam((Functor::Param)&somedata2, sizeof(char*), 1); // printf(somedata1, somedata2);
    MyFunc.Call(); // call printf

    //If youre calling a function that returns something, call it like this
    //    MyFunc.Call<returntype>()  and it will return what the function its calling returns
    return getchar();
}
Good luck, have fun, and sorry for not explaining first 8)

NOTE:
it(Functor::Call) uses dev c++ inline assembly syntax!(intel syntax..?)
it will probably fail on alot of other IDEs
Last edited on
Doesn't work with references:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

void add_int(int a, int b,int &ret)
{
  ret= a+b;
}

int main()
{
  int a=10,b=13,ret=0;

  Functor fn((Functor::Function)add_int,3);
  fn.SetParam(&a,sizeof(int),0);
  fn.SetParam(&b,sizeof(int),1);
  fn.SetParam(&ret,sizeof(int&),2);

  fn.Call();

  cout <<ret<<endl;


    return 0;
}

you need to pass the adresses of everything as void pointers;

fn.SetParam((Functor::Param)&a,sizeof(int),0);

I hope it works otherwise im going to slap my functor class
Im at work now btw so i cant test the code im writing =p
Last edited on
Still doesn't work with references:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void add_int(int a, int b,int &ret)
{
  ret= a+b;
}

int main()
{
  int a=10,b=13,ret=0;

  Functor fn((Functor::Function)add_int,3);
  fn.SetParam((Functor::Param)&a,sizeof(int),0);
  fn.SetParam((Functor::Param)&b,sizeof(int),1);
  fn.SetParam((Functor::Param)&ret,sizeof(int&),2);

  fn.Call();

  cout <<ret<<endl;


    return 0;
}


But that's not a big problem. Thanks anyway.

EDIT:
it(Functor::Call) uses dev c++ inline assembly syntax!(intel syntax..?)
Actually this is AT&T syntax.
Last edited on
Wait dude,

ret is an int, not an int reference.

hohohohoho

guess you cant pass int references as ints with my functor class ..

maybe this would work?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void add_int(int a, int b,int &ret)
{
  ret= a+b;
}

int main()
{
  int a=10,b=13,ret=0;
  int &ref = ret;

  Functor fn((Functor::Function)add_int,3);
  fn.SetParam((Functor::Param)&a,sizeof(int),0);
  fn.SetParam((Functor::Param)&b,sizeof(int),1);
  fn.SetParam((Functor::Param)&ref,sizeof(int&),2);

  fn.Call();

  cout <<ret<<endl;


    return 0;
}
Last edited on
ret is an int, not an int reference.

Oops my mistake. I wanted to say that add_int function takes int reference as third parameter.
Yeah i understand what you mean, you can normally pass ret as reference, the Functor class however..

Maybe i can get to fixing it sometime without a workaround
Topic archived. No new replies allowed.