Bytemaster's Boost Libraries
Quick Start
Boost.RPC

An example is worth a thousand words. We will start by creating a simple echo service. Defining the service is done entirely using Boost.Reflect.

JSON-RPC Client

    // echo_service.hpp
    struct echo_service {
        std::string echo( const std::string& s );
    };
    BOOST_REFLECT_ANY( echo_service, (echo) )

After defining our service, we can simply create a json::client from a json::tcp::connection.

    using namespace boost::rpc;

    json::tcp::connection::ptr con( new json::tcp::connection() );
    if( !con->connect( argv[1], argv[2] ) ) {
        std::cerr<<"Error connecting to "<<argv[1]<<":"<<argv[2]<<"\n"; 
        return;
    }
    json::client<echo_service> echo_client(con);
    std::string result = echo_client->echo( "Hello World" );

JSON-RPC Server

Defining the server is even easier.

    void create_session( const shared_ptr<echo_service>& es, const json::connection::ptr& con ) {
        json::server<echo_service> serv( es, con );
        boost::cmt::wait( con->disconnected );
    }

    shared_ptr<echo_service> es(new echo_service());
    json::tcp::listen( port, boost::bind(create_session, es, _1) );

Some things to note about the client and server are that they take a json::connection::ptr instead of a json::tcp::connection::ptr which means that they will work with any transport that implements a class derived from json::connection.

Add Command Line Interface to JSON Client

The following example really pulls everything together. It leverages the fact that boost::rpc::json::client<> inherits boost::reflect::any_ptr<> and therefore can be used by the general-purpose command line interpreter class that will allow us to enter commands like:

        echo( hello_world ) 

Have them parsed and then invoked via JSON RPC and then have the result handed back and printed to the screen.

See Boost.Reflect's Command Line Interpreter Example for more information.

    // Boost.CMT cannot block/wait from the main thread, so main simply kicks of
    // cmt_main as a new Boost.Context that can wait.
    void cmt_main( int argc, char** argv ) {
        using namespace boost::rpc;

        json::tcp::connection::ptr con( new json::tcp::connection() );
        if( !con->connect( argv[1], argv[2] ) ) {
            std::cerr<<"Error connecting to "<<argv[1]<<":"<<argv[2]<<"\n"; 
            return;
        }
        json::client<echo_service> echo_client(con);
        boost::reflect::any_ptr<echo_service> any_echo_service = echo_client;

        cli  m_cli(any_echo_service);

        boost::cmt::thread* getline_thread = boost::cmt::thread::create();
        while( true ) {
            std::cerr << "Enter Method: ";
            line = getline_thread->sync<std::string>( getline );
            cmd  = line.substr( 0, line.find('(') );
            args = line.substr( cmd.size(), line.size() );
            try {
                std::cerr << m_cli[cmd](args) << std::endl;
            } catch ( const std::exception& e ) {
                std::cerr << e.what() << std::endl;
            }
        }

    }
    int main( int argc, char** argv ) {
        boost::cmt::async( boost::bind( cmt_main, argc, argv ) );
        return boost::cmt::exec();
    }
 All Classes Namespaces Files Functions Variables Typedefs Defines