
On Sun, Feb 7, 2010 at 1:08 PM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
/* snip RPC stuff */
For note, I created an RPC system a while ago (of which I donated some of the code to RakNet, but my version is still more complete). It uses no macros, it handles overloads fine, and it was to be plugged into any system as well (I had a networking interface, as well as an interface into a little custom scripting language). It was used like this: // Some functions and member function to link in void _myFunc(someClass *m1, anotherClass &m2, yetAnotherClass m3, int i, float f, RPCInfo *rpc, std::string s) { /* do stuff */ } class myClass { public: void _myMemberFunc(int i, float f); static RPCHandler::type_of_callback<myClass::_myMemberFunc>::type myMemberFunc; } // You "register" it to the RPC system like this: RPCHandler global_rpc; auto myFunc = global_rpc.register(_myfunc, 0); // Either globally void someFunctionSomewhere(RPCHandler &rpc) { auto myLocalFunc = global_rpc.register(_myfunc1); // or locally // Registing a member function is the same way myClass::myMemberFunc = global_rpc.register(myClass::_myMemberFunc, "theMemberFunc") // and yes, the second parameter, the id, can be an int or string, whichever is easier for your situation } To use it you can set flags in the RPC class as to how to route that callback, whether it is local only, remote only, both, etc... And to use it, you just call the returned object from the register function as just any other function: myFunc(m1,m2,m3,42,3.14,"Hello World"); If that need to be called on a remote system, then it will be serialized up, sent out, and called remotely. If it is supposed to be called locally, then it will just call it locally right then and there. myClass m; myClass::myMemberFunc(m, 42, 3.14); // You would probably make a wrapped around this though... RPC calls can be registered at any time, and can be unregistered, and with bind they can be bound to specific objects and so forth as well. But the register call returns a specialized callback struct (that you can stuff into a boost::function if you do not care about overloading, or can be used as-is by the type_of_callback thing or auto). I had talked about this on boost before, hinted at making it a library, but no interest was expressed. I still have my code, it is well tested and in the wild (through RakNet), so if anyone is interested then I can clean it up and write documentation and submit it. The way it works though is just very heavy use of Boost.Fusion and function traits and a few other things. In the RakNet version I serialized things out to its bitstream, otherwise I use Boost.Serialization (which can be overridden to use yet another thing if you want, like I do for my scripting language version). But if a parameter is by value, it just packages it up according to Boost.Serialization (or whatever you use internally). If it is a reference or pointer it still follows the same serialization pattern, unless a few conditions are met. If it is a pointer or reference and it is to an RPCInfo type, then it passes in information about the call, like if it remote, local, and a few other things. In the RakNet version I added another overload so if a class was passed by pointer/reference and it was a subclass of NetworkIDObject, then instead of serializing the object it just sends its network ID number and looks up that same object on the remote system (perfect for *this and any other passed in parameters). It is easy to add new overrides too, and it threw a compile error in a specific spot if the thing could not be serialized and/or did not match other things and various other conditions as well, all compile-time. But yes, if anyone wants the code, I can easily give it, just no documentation and bit a messy, but it works quite well, no macros needed, no needing to register types, etc... And as you may notice, mine will silently drop return values, it is asynchronous only, but functionality like futures or synchronized calls could easily be added (although I would prefer async futures or async callbacks personally). And let me say, Boost.Fusion is so awesome!