XML-RPCのリクエストを処理してレスポンスを生成するためのフロントエンドのサンプルです。
XML-RPCのリクエストの本体は例えば以下のようなXMLです。
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
こう書くことで以下の手続きをどこかで実行しようとします。
examples.getStateName(41);
リクエストを送られた側は、リクエストを解釈して適切な関数を実行して返り値を返します。 これもXMLにして送り返す必要があって、それは例えば以下のようになります。
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>South Dakota</string></value>
</param>
</params>
</methodResponse>
こう書くことで、"South Dakota"という返り値を返しています。
このサンプルは、単一スレッドで動作するサンプルで、XML-RPCのリクエストとレスポンスをC++から簡単に生成したり取り扱うためのコードが実装されています。 バイナリXMLを用いることで、冗長なデータをやりとりするプロトコルのオーバーヘッドもいくらか削減することができます。
XML-RPCについては、XML-RPC仕様書の日本語訳が http://lowlife.jp/yasusii/stories/9.html にあります。
以下がサンプルのソースコードになります。
#include <vector>
#include "./xmlrpc_clientserver.h"
#include "./xmlrpc_value.h"
const int BUF_SIZE = 1024 * 128;
unsigned char g_Buf[BUF_SIZE];
class Sum : public XmlRpcServerMethod {
public:
explicit Sum(XmlRpcServer* server) : XmlRpcServerMethod(N("MyFunc.Sum"), server) {}
virtual void Execute(const XmlRpcValue& params, XmlRpcValue* result);
};
void Sum::Execute(const XmlRpcValue& params, XmlRpcValue* result) {
double sum = 0;
const XmlRpcArray* ar = params.AsArray();
size_t n = ar->Size();
for (size_t i = 0; i < n; ++i) {
const XmlRpcValue* item = ar->Get(i);
if (!item) continue;
if (item->GetValueType() == XmlRpcValue::INT) {
sum += *item->AsInt();
} else if (item->GetValueType() == XmlRpcValue::DOUBLE) {
sum += *item->AsDouble();
}
}
result->SetDouble(sum);
}
class MyServer {
XmlRpcServer m_Server;
std::vector<XmlRpcServerMethod*> m_Vec;
public:
MyServer() {}
~MyServer() {
size_t n = m_Vec.size();
for (size_t i = 0; i < n; ++i) delete m_Vec[i];
}
void SetupMethods() {
Sum* sum = new (std::nothrow) Sum(&m_Server);
m_Vec.push_back(sum);
}
XmlRpcServer* GetServer() { return &m_Server; }
};
MyServer g_Server;
bool SampleMain(int, char**) {
g_Server.SetupMethods();
XmlRpcClient client;
client.SetServer(g_Server.GetServer());
XmlRpcValue params;
params.SetArray();
params.AsArray()->Append()->SetDouble(1.0);
params.AsArray()->Append()->SetInt(2);
params.AsArray()->Append()->SetDouble(3.0);
XmlRpcValue result;
XmlRpcCallResult future;
if (!client.Execute(N("MyFunc.Sum"), params, &future)) {
return false;
}
if (!future.GetResult(&result)) {
return false;
}
nlib_printf(
"%f\n", *result.AsArray()->Get(0)->AsDouble());
return true;
}
NLIB_MAINFUNC