似非 RPC

大量のメモリを消費するライブラリの場合,普通のマシンで実行するのは難しいので,RPC(Remote Procedure Call)っぽいものを実装する簡単な方法がないか考え中です.それで,現在のところ,C++ では Boost と protobuf を組み合わせればいいかもしれないと思っています.
幸いにも,protobuf は C#Perl でも使えそうですし,これらの言語なら通信機能もデフォルトで備わっています.環境の違い(Windows, Linux, Mac)や言語の違い(C++, Perl, etc)があってもなんとかなりそうなので,お試し中です.

#ifndef RPC_CLIENT_BASE_H
#define RPC_CLIENT_BASE_H

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

#include <string>

namespace rpc
{

template <typename RequestType, typename ResponseType,
	int MinBufSize = 1, int MaxBufSize = 1 << 20>
class ClientBase
{
public:
	typedef RequestType request_type;
	typedef ResponseType response_type;

	// Size range.
	enum { MIN_BUF_SIZE = MinBufSize, MAX_BUF_SIZE = MaxBufSize };

public:
	// Opens a connection to a specified server.
	ClientBase(const std::string &host, unsigned short port)
		: stream_(host, boost::lexical_cast<std::string>(port)) {}
	// Connects to a specified server.
	ClientBase(const std::string &host, const std::string &port)
		: stream_(host, port) {}

	// Downloads a specified page.
	bool invoke(const request_type &request, response_type *response)
	{
		if (!stream_)
			return false;

		// Sends a request.
		std::string buf;
		if (!request.SerializeToString(&buf)
			|| !(stream_ << buf.size() << '\n' << buf))
			return false;

		// Receives a response.
		std::size_t buf_size;
		if (!(stream_ >> buf_size).ignore()
			|| buf_size < MIN_BUF_SIZE || buf_size > MAX_BUF_SIZE)
			return false;

		buf.resize(buf_size);
		if (!stream_.read(&buf[0], buf_size)
			|| !response->ParseFromString(buf))
			return false;

		return true;
	}

	// Checks if a connection is opened or not.
	bool is_open() const { return !!stream_; }

private:
	boost::asio::ip::tcp::iostream stream_;
};

}  // namespace rpc

#endif  // RPC_CLIENT_BASE_H

# 研究室なのに Windows 使いばかりで不便….