Sample of a front-end that processes an XML-RPC request and generates a response.
The body of the XML-RPC request is XML similar to the following.
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
By writing the XML in this way, it attempts to run the following procedure at certain timing:
examples.getStateName(41);
The application that receives the request parses the request, runs the appropriate function, and returns the return value. The response must also be sent back in XML format, and might look something like the following.
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value><string>South Dakota</string></value>
</param>
</params>
</methodResponse>
This sample sends "South Dakota" as the return value.
It is just a single-threaded sample that implements code for easily generating and handling a XML-RPC request and response from C++. The use of binary XML provides a moderate reduction in overhead for the protocol used to exchange the otherwise verbose data.
The Japanese translation of the XML-RPC specifications can be found here. http://lowlife.jp/yasusii/stories/9.html
The source code of the sample is shown below.
#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