7

I am relatively new to C++ - I leanerd it some 6+ years ago, but have never really used it until some months ago.

What is the scenario:

  • Considerably large system with a lot of modules.

Desired Output:

  • Modules (namely X) "expose" certain functions to be called over network and have the result sent back to the caller (namely Y)
  • The caller Y doesn´t know any info about X, despite what was exposed by the library (function name and parameters).
  • The calling of function in X from the library will have to happen through a string received from Y - or a set of strings, as there will be parameters as well.

Ideally what I want to have is something as generic as possible with variable return/paramaters types, or some kind of type-erasure - owing to the fact that I don´t know which functions each module will want to expose. I reckon its quite utopic to get something like that running in C++. But hopefully with pre-determined possible return/parameter types, it is feasible. The communication is not a problem for now, what matters is what should be done in the module side.

Question:

  • Would it be possible to accomplish such thing using C++ and Boost ? I would be really greateful if someone could give me some guidelines - literature/tutorials/(pseudo)code examples and so on and so forth. I am ofc not expecting a full solution here.

Possible solution:

I am a little bit lost as to which "functionalities" of the languages I can/should use - mainly due to my restrictions in the project.

I thought about using Variadic Templates and found the question below, which really helps, the only problem is that Variadic Templates are not supported in VS2010.

Generic functor for functions with any argument list

After some extensive research in the Web, the closest answer I got was this:

map of pointers to functions of different return types and signatures

The scenario is pretty much the same. The difference, however, seems to me that the OP already knows beforehand the return/parameters the functions he will be using. Due to my low reputation (I just joined) I unfortunately cannot ask/comment anything there.

TBH I didn´t get that well how to accomplish what the selected answer explains.

Using maps is a way, but I would have to store objects which contains function pointers (as also answered in the question), but as it is possible to see in the provided code by the user, it does have some hard-coded stuff which I wasn´t desiring to have.

Further clarifications:

  • Yes, I am restricted to use C++ AND VS2010 SP1.
  • No, despite Boost, I cannot use any other 3rd library - it would be great to be able to use some Reflection libraries such as CPGF http://www.cpgf.org/ (even though I am not 100% sure if thats what I really need)

Minor Edit: - Scripting language bindings (such as LUA) are indeed a way to go, yet I didn´t want to include it in the project.

I hope someone can shed light on this problem!

Thanking in advance for any input!

Community
  • 1
  • 1
skullmetal
  • 91
  • 3
  • 1
    It sounds like the same problem faced when exposing c++ functions and classes to scripting languages (e.g lua) so you could look at how those are implemented for inspiration. (e.g. http://www.rasterbar.com/products/luabind.html) – benjymous Dec 18 '13 at 10:10
  • 4
    Looks like you want an RPC system. There are tons of those, e.g. Apache Thrift. – Kerrek SB Dec 18 '13 at 10:11
  • Thanks for such prompt input from you both. I will definitely look into it! I just remembered about the scripting language bindings which are not what I exactly wanted to include in the project ( I will edit the post). However, if there´s no other way, then I will have to see what it can be done! – skullmetal Dec 18 '13 at 10:23
  • How are you using these functions in Y? Not the mrchanics of the call: but how does Y know to call a particular function -- who tells it? It cannot know without some external information. Are there scripts? User input? Is there some code that assumes `X` will have some functions that routes the calls through `Y`? – Yakk - Adam Nevraumont Dec 18 '13 at 11:33
  • @Yakk Y is an UI, therefore the user will decide which function he wants to call and the parameters to be passed along it. The UI itself will be responsible for querying modules for available commands. Did I answer everything? – skullmetal Dec 18 '13 at 11:50
  • @skullmetal so why does.the ui not bundle the parameters and arguments together itself, or even call them? Why is `X` involved at all? – Yakk - Adam Nevraumont Dec 18 '13 at 13:50
  • @Yakk Im not sure if I followed you correctly. The UI and modules will be in different systems, and communicating through network. The library should be responsible for managing the communication between X and Y, as well as executing the commands in X side and returning the results. UI will as well implement the library, but I cannot see what you suggested happening! To my eye, the main logic is happening in X side and not the opposite. – skullmetal Dec 18 '13 at 14:08

1 Answers1

2

Looks like you're needed a little reflection module. For example we have a struct of method info such as:

struct argument_info {
    std::string name;
    std::string type;
    std::string value;
}

struct method_info {
    std::string method_name;
    std::string return_type;
    std::list<argument_info> arguments;
}

then compile a dll with all exported functions

extern"C" __declspec(dllexport) void f1(int a, int b){/*...*/}
extern"C" __declspec(dllexport) int f1(std::string a, int b, char* c){ return x; }

in the interpreter's code:

void call_function(method_info mi, argument_info& t_return)
{
    /* let g_mi be a map, where key is a std::string name of the method and the 
       value is method_info struct */ 
    if(!g_mi->find(mi.method_name))
        throw MethodNotFindException

    if(g_mi[mi.method_name].arguments.size() != mi.arguments.size())
        throw InvalidArgumentsCountException;

    for(int i = 0; i < g_mi[mi.method_name].arguments.size(); i++)
    {
        if(g_mi[mi.method_name].arguments[i].type != mi.arguments[i].type)
            throw InvalidArgumentException;
    }

    t_return = module->call(mi.arguments); 
}

I hope it may help you.

Netherwire
  • 2,669
  • 3
  • 31
  • 54
  • Please correct me if I misunderstood it, but I would need to compile the functions in the modules X into a DLL? If this is the case, I am afraid this would not help me, as I don´t have any control on the Modules, just the developers, therefore, I am to provide the simplest way possible. Simple as "I want this function to be called from outside! Do the rest". – skullmetal Dec 18 '13 at 12:10
  • So sorry, I've misunderstood. – Netherwire Dec 18 '13 at 15:06
  • Your problem is complicated, but it seems like cpgf meets your critera, there's also boost::python, don't know how 'bout lua. So, take a look inside. – Netherwire Dec 18 '13 at 15:12
  • Thanks for the time to answer, anyway! Much appreciated! Regarding the scripting languages, I will try not to touch for as long as I can. I have some restriction in the project which won´t allow me that easily to put other libraries. – skullmetal Dec 19 '13 at 08:27