
2011/2/14 Daniel Larimer <dlarimer@gmail.com>:
I have posted Boost.IDL to github complete with documentation here: http://bytemaster.github.com/boost_idl/index.html
https://github.com/bytemaster/boost_idl
The library is header only. It is included as part of the Boost.Defrag "incubating" projects.
The documentation includes several examples of how it is used to provide a simple 'command line interface' to a struct as well as a fully 'generic' RPC example that will expose any interface over the network using Boost.Serialization. Full RPC implementation 245 SLOC. The RPC example is very 'bare bones' because I think that a Boost.RPC library should be a separate project.
I welcome any feedback.
The code is still very 'new' and has not been tested on any platforms other than OS X, but it should all be very portable as I write Mac/Linux/Windows portable software every day. Server:
struct Echo { std::string echo(const std::string &s) { return s; } }; BOOST_IDL_INTERFACE( Echo, BOOST_IDL_BASE, (echo) )
int main() { boost::idl::rpc_server<Echo> server( Echo() ); server.listen( 50001 ); return 0; } Client:
struct Echo { std::string echo(const std::string &s); // implementation not needed }; BOOST_IDL_INTERFACE( Echo, BOOST_IDL_BASE, (echo) )
int main() { boost::idl::rpc_client<Echo> client; client.connect_to( "localhost", 50001 ); std::string s = client.echo( "what's up" ); return 0; }
Type Erasure Applied to rpc_client: // erase the details of the rpc_client, by storing // it in a generic Echo interface. boost::idl::any<Echo> any_echo = client;
Command Line Interface: template<typename InterfaceType,typename InterfaceDelegate> void start_cli( boost::idl::any<InterfaceType,InterfaceDelegate>& a ) { cli m_cli; m_cli.start_visit(a);
std::string line; std::string cmd; std::string args;
while( true ) { std::cerr << "Enter Method: "; std::getline( std::cin, line ); cmd = line.substr( 0, line.find('(') ); args = line.substr( cmd.size(), line.size() ); std::cerr << m_cli[cmd](args) << std::endl; } }
I haven't carefully read the documentation (sorry, have no time now), but I thought a lot about a new serialization library. My opinion is that this library couples two things together: interfaces and reflection. I think that the correct approach to this is: 1.- Build a general runtime concepts library (without reflection) 2.- Build a reflection mechanism that would be possible for every c++ type to use (non-intrusive). 3.- Build serialization and other reflection mechanisms in top of these two different libraries. I tried (but it's incomplete) a new reflection approach, and I think that with c++0x will be possible. The goal for this reflection library was serialization, so it wasn't a general reflection framework, but it was good enough to serialize objects. My approach was to use a tuple that described every c++ member that a class had. It looked something like this: class MyClass { typedef MyClass this_class; std::string val_; float f_; public: typedef std::tuple<MEM_VARS2(val_, f_)> serializable_members_t; }; And the rest was done by a general serialize member function (actually a family with boost::enable_if). With c++0x I could pass the variable names in tuples if we had user-defined literals and constexpr (at least, I think so). With this info, it's very easy to serialize objects in c++ (although I didn't study every single problem like inheritance and so on). template <class T> std::string serialize(const T & t); With reflection for members and runtime concepts, a framework for RPC can be built on top of those general and useful by themselves library. I hope my opinion helped you. ______________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost