Click here to Skip to main content
16,011,647 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I am looking for a class/library that can generate (parameterless void) functions that consist of function calls with consts. Usage would be something like

generator.startFunction();
generator.addCall(funcPtr);
generator.addParam(1);
generator.addParam(&someVar);
... //More calls
funcPtr newFunc = generator.compile();
newFunc();


I'm ok with the user being responsible for correctly matching function signatures with parameters, and for the calling conventions to be the same for all functions. I would like to be able to call class member functions as well, but it isn't a must.

Does anyone know of a library with this kind of functionality? If not, does anyone know a good resource with the ASM knowledge required to do this?

Thanks!
Posted
Updated 12-Jul-10 1:01am
v2

For the sake of completeness (maybe someone will search for something similar someday), here is the finished demo :

C++
#include <iostream>
#include <vector>
//Some test functions and classes
int callMe() { std::cout << "callMe()\n"; return 1; }
void callMeWithInt(int a) { std::cout << "callMeWithInt(" << a << ")\n"; }
void callMeWithFloat(float a) { std::cout << "callMeWithFloat(" << a << ")\n"; }
class Foo { public : virtual void bar() { std::cout << "Foo::bar()\n"; } };
class Doo : public Foo { public: virtual void bar() { std::cout << "Doo::bar()\n"; } };
//The interface
class FunctionCaller { public : virtual void call() = 0; };
//The template implementations of the interface
template <typename RetValT> class NoParamCaller : public FunctionCaller
{
    typedef RetValT (*NoParamFunc)();
    NoParamFunc theFunc;
public:
    NoParamCaller(NoParamFunc func) : theFunc(func) {};
    void call() { theFunc(); }
};
template <typename RetValT, typename Param1T> class OneParamCaller : public FunctionCaller
{
public:
    typedef RetValT (*OneParamFunc)(Param1T);
    OneParamFunc theFunc;
    Param1T param1;
    OneParamCaller(OneParamFunc _func, Param1T _param1) : theFunc(_func), param1(_param1) {};
    void call() { theFunc(param1); }
};
template <class ClassT, typename RetValT> class NoParamClassCaller : public FunctionCaller
{
public:
    typedef RetValT (ClassT::*NoParamFunc)();
    NoParamFunc theFunc;
    ClassT* theInstance;
    NoParamClassCaller(ClassT* instance, NoParamFunc func) : theInstance(instance), theFunc(func) {}
    void call() { (theInstance->*theFunc)(); }
};

//Example usage
int main(int argc, char* argv[])
{
    //Fill up the call object
    std::vector<FunctionCaller*> calls;
    calls.push_back(new NoParamCaller<int>(callMe));
    calls.push_back(new OneParamCaller<void, int>(callMeWithInt, 1));
    calls.push_back(new OneParamCaller<void, float>(callMeWithFloat, 5.5));
    Foo foo;
    calls.push_back(new NoParamClassCaller<Foo, void>(&foo, &Foo::bar));
    Foo* doo = new Doo();
    calls.push_back(new NoParamClassCaller<Foo, void>(doo, &Foo::bar));
    //This can be repeated many times
    for (size_t i=0; i<calls.size(); i++)
    {
        calls[i]->call();
    }
    //Cleanup
    for (size_t i=0; i<calls.size(); i++)
    {
        delete calls[i];
    }
    calls.clear();
    delete doo;
    std::cout << "Finished" << std::endl;
    return 0;
}


With demonstrated support for member functions as well, with overriding virtual functions behaving correctly.
 
Share this answer
 
I went for a slightly different approach. Something similar to boost::function but allowing me to bake the parameters in during call preparation. Here is a small test app I wrote :

C++
#include <iostream>
#include <vector>
typedef void (*VoidFunc)();
int callMe() { std::cout << "callMe()\n"; return 1; }
void callMeWithInt(int a) { std::cout << "callMeWithInt(" << a << ")\n"; }
void callMeWithFloat(float a) { std::cout << "callMeWithFloat(" << a << ")\n"; }
class FunctionCaller { public : virtual void call() = 0; };
template <typename RetValT> class NoParamCaller : public FunctionCaller
{
    typedef RetValT (*NoParamFunc)();
    NoParamFunc theFunc;
public:
    NoParamCaller(NoParamFunc func) : theFunc(func) {};
    void call() { theFunc(); }
};
template <typename RetValT, typename Param1T> class OneParamCaller : public FunctionCaller
{
public:
    typedef RetValT (*OneParamFunc)(Param1T);
    OneParamFunc theFunc;
    Param1T param1;
    OneParamCaller(OneParamFunc _func, Param1T _param1) : theFunc(_func), param1(_param1) {};
    void call() { theFunc(param1); }
};
int main(int argc, char* argv[])
{
    std::vector<FunctionCaller*> calls;
    calls.push_back(new NoParamCaller<int>(callMe));
    calls.push_back(new OneParamCaller<void, int>(callMeWithInt, 1));
    calls.push_back(new OneParamCaller<void, float>(callMeWithFloat, 5.5));
    for (size_t i=0; i<calls.size(); i++)
    {
        calls[i]->call();
    }
    for (size_t i=0; i<calls.size(); i++)
    {
        delete calls[i];
    }
    calls.clear();
    std::cout << "Finished" << std::endl;
    return 0;
}


This code compiles and runs correctly. I have the FunctionCaller interface, which then gets implemented by the template classes. In this case, I only handle 0 or 1 parameters, but adding the same templates for the 2,3,4 cases (should be enough) and maybe the member function permutation as well will not be that hard.

Then, instead of having the generated function, i will have an array of FunctionCallers that i will need to call. The overhead is probably 2-3 times bigger than the assembly writing route (have to access the array and another virtual function call), but I can manage that cost.

Does this seem OK for what I'm trying to do? Anybody see something inherently wrong with it?
 
Share this answer
 
Comments
Aescleal 12-Jul-10 9:41am    
Firstly I'd add a virtual destructor to your base class otherwise things might go a bit pear shaped if you ever handle functions that use objects with destructors as parameters.

Secondly if you really must new the objects in the array use a smart pointer to automate your cleanup. It improves the exception safety no end. I'd also consider getting rid of the explicit loop as well, but that'll take a shim function or function object (a lambda would work if your compiler supports it).

Cheers,

Ash
Noam dev 12-Jul-10 10:30am    
Obviously this is not an infrastructure, just a proof of concept.
If I do decide to go with this route, the code will be in production level standards (it is very far from that currently...)
Seeing your comment to Cedric's answer, you've got a couple of options.

The first one is fight your way through boost::function and use that. You should be able to bind functions, objects, member functions and their parameters using that. If you want complete binding at run time (i.e. when you wander into a function you don't know what type of function and types/values of parameters) then this isn't going to work.

A dirtier approach that doesn't use boost would be to come up with small function objects yourself. The classes are usually fairly small when you do this sort of thing and in some cases you can even use the standard library.

So if I've got a class A with a function b that takes one int parameter and I want to call b on a collection of A's with the same parameter:

class A
{
    public:
        void b( int n )
        {
            std::cout << "b called with..." << n << std::endl;
        }
};


you can call A::b with a constant parameter for a collection of A's:

std::vector<A> a_array( 16 );
std::for_each( a_array.begin(), a_array.end(), std::bind2nd( std::mem_fun_ref( &A::b ), 5  ) );


Hope this helps,

Cheers,

Ash
 
Share this answer
 
Could you explain why you would like something like that ? There are probably solutions to your problem but it would help a lot if you provide the context.
What you described here doesn't make a lot of sense because the code you wrote could be replaced by the direct call to the function. I guess you are instead looking for some kind of scripting, am I right ?
 
Share this answer
 
Comments
Noam dev 12-Jul-10 8:05am    
I have a system with many parameters (the OpenGL/DirectX render context, but that is irrelevant), and many objects that need to set the system to a certain state (Lets call them passes).

Normally, I can just set the state parameter by parameter, or even check each parameter to see if they are different. However, this is very costly - subsequent objects usually differ by very little (1 or 2) parameters, but the total amount of checks/sets is between hundreds to thousands. Moreso, some of the checks/sets are very costly by themselves, so I would like to reduce them as much as possible.

What I would like to do, is to bake 'pass transition' functions, that once generated (per from-to pass combination), will contain the exact calls required to change to the state. That is what I need this library for

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900