xmlrpc for c and c++(xmlrpc-c)をWindows10, openFrameworks環境で使う
XML-RPCは古いインターフェースですが、Pythonの標準ライブラリでサーバーが簡単に作れるので、C++からPythonを呼び出したい時など、時と場合によっては便利に使えます。以前libxmlrpc++を紹介したことがありますが、今回のはxmlrpc for c and c++(xmlrpc-c)です。違いは、xmlrpc-cは非同期(Asynch≒non-blocking)に対応していること(ただしインターフェースは洗練されていない)です。
CMakeサポート版のフォーク xmlrpc-c
github.com
個人のgraugansさんが作られたもので、5か月ぐらい前が最終更新のタイムスタンプです。
HTTP用の外部ライブラリが必要で、
- Curl
- Libwww
- Wininet
から選んで使います。Curlが推奨されていますが、Windowsでは標準で使えるWininetでも特に問題は感じません。ここでは、Wininetを使うことにします。
CMakeLists.txtを編集
どのライブラリを選択してもfindCurlを必ず呼んでここで引っかかってしまうので、コメントアウトしてしまいます。乱暴なことをしていますので、何があっても責任取れません。自分で判断して使ってください。
#find_package(CURL ${tmp})
#ensc_set_bool(MUST_BUILD_CURL_CLIENT ${CURL_FOUND} "Set if Curl client transport shall be built")
あとは普通にcmakeでconfigureとgenerateしてプロジェクトを作ってください。
build
普通にビルドをすると半分ぐらいビルドできますが、半分ぐらいエラーで落ちます。適当にCMakeLists.txtを適当に編集したためにMUST_BUILD_CURL_CLIENTの定義が抜けてしまっているためです。次のように修正します。
transport_config.h
/* -*- c -*- */ #define MUST_BUILD_WININET_CLIENT 1 #define MUST_BUILD_LIBWWW_CLIENT 0 #define MUST_BUILD_CURL_CLIENT 0 //////
bin, include, libを集める
出力ファイルは何故かあちこちにバラバラに配置されています。
cライブラリは、build/src/ReleaseもしくはDebugに.dllと.libがあります。
c++ライブラリは、build/src/cpp/Release もしくはDebugに.dllと.libファイルがあります。
xmlrpc_util.dllとxmlrpc_util.libは、build/lib/libutil/ReleaseもしくはDebugにあります。
includeファイルは、include/xmlrpc-cにあります。
config.hは、build/include/xmlrpc-cにあります。
自分の都合の良いように、適当なフォルダの中にそれぞれ放り込んでください。
サンプルプログラム
たとえば非同期クライアントを動かしてみます。Curlを使っていませんので、Curl対応の関数を読んでいるところをwininet用関数に置き換えます。
https://sourceforge.net/p/xmlrpc-c/code/HEAD/tree/trunk/examples/cpp/asynch_client.cpp
//xmlrpc_c::clientXmlTransport_curl myTransport;
xmlrpc_c::clientXmlTransport_wininet myTransport;
Resultが構造体だったりArrayだったりするときのデータ受け取り方法
xmlrpc++はとてもスマートに直感的にかけたのですが、xmlrpc-cは残念ながらいまいちです。返り値が構造体の場合は、下記のようにデータを解釈させます。
構造体受信の例
jntという名前のdouble型arrayが入っている構造体の受信例です。
string const serverUrl("http://192.168.0.11:4321"); string const methodName("get_joint"); xmlrpc_c::clientSimple myClient; xmlrpc_c::value result; myClient.call(serverUrl, methodName, "", &result); xmlrpc_c::value_struct s(result.cValue()); xmlrpc_c::value_array a(s.cvalue()["jnt"]); for (int i = 0; i < 6; i++) { joint[i] = xmlrpc_c::value_double(a.cvalue()[i]); }
構造体送信の例
xmlrpc_c::clientXmlTransport_wininet myTransport; xmlrpc_c::client_xml myClient(&myTransport); string const methodName("move_joint"); xmlrpc_c::carray a; for (int i = 0; i < 6; i++) { a.push_back(xmlrpc_c::value_double(joint[i])); } xmlrpc_c::cstruct s; s.insert(std::make_pair<std::string, xmlrpc_c::value>("", xmlrpc_c::value_array(a))); xmlrpc_c::paramList sampleAddParms1; sampleAddParms1.add(xmlrpc_c::value_struct(s)); xmlrpc_c::rpcPtr rpc1P(methodName, sampleAddParms1); string const serverUrl("http://192.168.0.11:4321"); xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl); rpc1P->start(&myClient, &myCarriageParm); myClient.finishAsync(xmlrpc_c::timeout(100));
今日のノートPC
アマゾン専売のMSIの軽量14インチノート。11万円ぐらいでGeForceMX150搭載。自宅用はもうこれで良いね。
[asin:B07D8PJBGS:detail]
[asin:B07FB27SNB:detail]