MSGPACK_DEFINEが32個までしか対応していない問題
msgpackについては以下を参照
問題
MSGPACK_DEFINEで33個以上の引数を取ることができなかった
msgpackのバージョン
現在のmasterのバージョンは2.1.5
https://github.com/msgpack/msgpack-c/blob/master/CHANGELOG.md
MSGPACK_DEFINEとは
保存したいクラスのメンバ変数を、MSGPACK_DEFINEマクロに入れると、 自動でシリアライズ/デシリアライズできる
https://github.com/msgpack/msgpack-c/blob/master/QUICKSTART-CPP.md#user-defined-classes
You can use serialize/deserializes user-defined classes using MSGPACK_DEFINE macro.
ソースコード
MSGPACK_DEFINEの数が32のファイル
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_before-expand32.cpp #include <msgpack.hpp> #include <vector> #include <string> #include <iostream> class myclass { public: std::string var[32]; MSGPACK_DEFINE( var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31]); myclass() { var[0] = "0"; var[1] = "1"; var[2] = "2"; var[3] = "3"; var[4] = "4"; var[5] = "5"; var[6] = "6"; var[7] = "7"; var[8] = "8"; var[9] = "9"; var[10] = "10"; var[11] = "11"; var[12] = "12"; var[13] = "13"; var[14] = "14"; var[15] = "15"; var[16] = "16"; var[17] = "17"; var[18] = "18"; var[19] = "19"; var[20] = "20"; var[21] = "21"; var[22] = "22"; var[23] = "23"; var[24] = "24"; var[25] = "25"; var[26] = "26"; var[27] = "27"; var[28] = "28"; var[29] = "29"; var[30] = "30"; var[31] = "31"; } }; int main(void) { std::vector<myclass> vec; // add some elements into vec... vec.push_back(myclass()); // you can serialize myclass directly msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec); msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size()); msgpack::object obj = oh.get(); // you can convert object to myclass directly std::vector<myclass> rvec; obj.convert(rvec); for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) { for(int i = 0; i < 32; i++) { std::cout << (*it).var[i] << std::endl; } } } [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $
コンパイルと実行結果
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_before-expand32.cpp [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $
これはできる
MSGPACK_DEFINEの数が33のファイル
上のファイルで33個目を追加するとコンパイルに失敗
コンパイルエラー抜粋
/usr/local/include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp:4468:171: note: template argument deduction/substitution failed: In file included from /usr/local/include/msgpack/adaptor/define.hpp:13:0, from /usr/local/include/msgpack/type.hpp:25, from /usr/local/include/msgpack.hpp:18, from msgpack_define_before-expand33.cpp:1: msgpack_define_before-expand33.cpp:10:5: note: candidate expects 32 arguments, 33 provided MSGPACK_DEFINE( ^ In file included from /usr/local/include/msgpack/v1/adaptor/define.hpp:14:0, from /usr/local/include/msgpack/adaptor/define.hpp:15, from /usr/local/include/msgpack/type.hpp:25, from /usr/local/include/msgpack.hpp:18, from msgpack_define_before-expand33.cpp:1:
MSGPACK_DEFINEの定義
return define_array<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31>(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31);
- MSGPACK_DEFINEで呼んでいる関数には32個までしか対応していない
対応策
考えられる対応策は以下の3つ
以下詳細を説明
案1.c++11にする
c++11なら出来るらしい
msgpackの1.0以上、かつc++11だったら33個以上もできそう https://github.com/msgpack/msgpack-c/issues/11
for c++98, we can't extend it easily, all we can do is just write extra specialization for more args. but for c++11, we can use variadic template to break it, although, there is limit, but it's compiler's business.
これができるならそれで問題ない
c++11でコンパイルが通ることを確認
上でコンパイルエラーになったmsgpack_define_before-expand33.cppをc++11でコンパイル
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include -std=c++11 msgpack_define_before-expand33.cpp [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $
案2.MSGPACK_DEFINEを入れ子にする
- 例えば、stuct Aに33個以上の項目を入れてまとめてMSGPACK_DEFINEをしようとすると失敗する
- そこで、別にstruct Bを用意して、その中に項目を入れて、MSGPACK_DEFINEし、さらにそのstructBをstructAの一要素とすれば(入れ子にすれば)、それぞれのstructの項目数は32個を超えずに済む
- 多分これでもできそうだが、入れ子になるのが気持ち悪かったので試してない
案3.拡張版のMSGPACK_DEFINEを作成する
- msgpack 0.5ではかんたんだったけど、最新版は難しい
手順1.拡張版ファイルの作成
https://github.com/msgpack/msgpack-c/tree/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/erb/v1
ここのerbのGENERATION_LIMIT = 31を40とかに書き換える
今回上のソースコードで使っているのはarrayだけなので、arrayとそこでつかっているtupleだけ増やしたファイルを用意すればいい(mapは不要) なので、以下のファイルのLIMITを40とかに書き換える
- cpp03_msgpack_tuple_decl.hpp.erb
- cpp03_msgpack_tuple.hpp.erb
- cpp03_define_array_decl.hpp.erb
- cpp03_define_array.hpp.erb
あとは、以下のファイルを実行すれば、修正したerbをもとに拡張版のヘッダファイルが自動で作成される
https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/preprocess
rubyが無いと言われたので以下でインストール
# apt-add-repository ppa:brightbox/ruby-ng // レポジトリの追加 # apt-get update // # apt-get install ruby2.2 // ruby(バージョン)のインストール
手順2.作ったファイルでライブラリのファイルを置き換える
これで作ったファイルを実際のmsgpackファイルと置き換える
- 以下のファイルをつくったファイルと置き換える
- /usr/local/include/msgpack/v1/adaptor/detail
これで実行すると、拡張版を使って33以上の項目もMSGPACK_DEFINEできる
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_expand33.cpp #include <msgpack.hpp> #include <vector> #include <string> #include <iostream> class myclass { public: std::string var[33]; MSGPACK_DEFINE( var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31], var[32]); myclass() { var[0] = "0"; var[1] = "1"; var[2] = "2"; var[3] = "3"; var[4] = "4"; var[5] = "5"; var[6] = "6"; var[7] = "7"; var[8] = "8"; var[9] = "9"; var[10] = "10"; var[11] = "11"; var[12] = "12"; var[13] = "13"; var[14] = "14"; var[15] = "15"; var[16] = "16"; var[17] = "17"; var[18] = "18"; var[19] = "19"; var[20] = "20"; var[21] = "21"; var[22] = "22"; var[23] = "23"; var[24] = "24"; var[25] = "25"; var[26] = "26"; var[27] = "27"; var[28] = "28"; var[29] = "29"; var[30] = "30"; var[31] = "31"; var[32] = "32"; } }; int main(void) { std::vector<myclass> vec; // add some elements into vec... vec.push_back(myclass()); // you can serialize myclass directly msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec); msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size()); msgpack::object obj = oh.get(); // you can convert object to myclass directly std::vector<myclass> rvec; obj.convert(rvec); for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) { for(int i = 0; i < 33; i++) { std::cout << (*it).var[i] << std::endl; } } } [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $
コンパイルと実行
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_expand33.cpp [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ← 33個目が使えている! [~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $
c++のメモ
概要
c++についての自分用のメモ書き
g++
g++ がサポートしている規格
$ g++ --version g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ g++ -v --help 2>/dev/null | grep -E "^\s+\-std=.*$" -std=<standard> Assume that the input sources are for <standard> -std=f2003 Conform to the ISO Fortran 2003 standard -std=f2008 Conform to the ISO Fortran 2008 standard -std=f2008ts Conform to the ISO Fortran 2008 standard -std=f95 Conform to the ISO Fortran 95 standard -std=gnu Conform to nothing in particular -std=legacy Accept extensions to support legacy code -std=c++03 Conform to the ISO 1998 C++ standard revised by -std=c++0x Deprecated in favor of -std=c++11 -std=c++11 Conform to the ISO 2011 C++ standard -std=c++1y Conform to the ISO 201y(7?) C++ draft standard -std=c++98 Conform to the ISO 1998 C++ standard revised by -std=c11 Conform to the ISO 2011 C standard (experimental -std=c1x Deprecated in favor of -std=c11 -std=c89 Conform to the ISO 1990 C standard -std=c90 Conform to the ISO 1990 C standard -std=c99 Conform to the ISO 1999 C standard -std=c9x Deprecated in favor of -std=c99 -std=gnu++03 Conform to the ISO 1998 C++ standard revised by -std=gnu++0x Deprecated in favor of -std=gnu++11 -std=gnu++11 Conform to the ISO 2011 C++ standard with GNU -std=gnu++1y Conform to the ISO 201y(7?) C++ draft standard -std=gnu++98 Conform to the ISO 1998 C++ standard revised by -std=gnu11 Conform to the ISO 2011 C standard with GNU -std=gnu1x Deprecated in favor of -std=gnu11 -std=gnu89 Conform to the ISO 1990 C standard with GNU -std=gnu90 Conform to the ISO 1990 C standard with GNU -std=gnu99 Conform to the ISO 1999 C standard with GNU -std=gnu9x Deprecated in favor of -std=gnu99 -std=iso9899:1990 Conform to the ISO 1990 C standard -std=iso9899:199409 Conform to the ISO 1990 C standard as amended in -std=iso9899:1999 Conform to the ISO 1999 C standard -std=iso9899:199x Deprecated in favor of -std=iso9899:1999 -std=iso9899:2011 Conform to the ISO 2011 C standard (experimental
引数
引数を2倍して出力する
参考 - C++で文字列を数値に変換する方法 - C++と色々 - http://www7b.biglobe.ne.jp/~robe/cpphtml/html03/cpp03042.html
https://github.com/ludwig125/work/blob/master/src/cpp/test/argv.cpp
#include <iostream> #include <stdlib.h> using namespace std; int main(int argc, char** argv) { for(int i = 1; i < argc; i++){ cout << "argv "<< i << " : " << argv[i] << endl; cout << "double argv: " << atoi(argv[i])*2 << endl; } return 0; }
実行結果
$ g++ argv.cpp [~/git/work/src/cpp/test ] $ ./a.out 13 83 argv 1 : 13 double argv: 26 argv 2 : 83 double argv: 166
型変換
- 変数の型変換
型を確認
#include <iostream> #include <stdlib.h> #include <typeinfo> using namespace std; int main(int argc, char** argv) { int a,b; for(int i = 1; i < argc; i++){ cout << "argv "<< i << " : " << argv[i] << endl; } // 引数の型 cout << typeid(argv[1]).name() << " : " << argv[1] << endl; a = atoi(argv[1]); b = atoi(argv[2]); // 変換後の型 cout << typeid(a).name() << " : " << a << endl; return 0; }
実行結果
$ ./a.out 10 30 argv 1 : 10 argv 2 : 30 Pc : 10 i : 10
typeidの出力
Uses of typeid in C++ - Codeforces
bool = b char = c unsigned char = h short = s unsigned short = t int = i unsigned int = j long = l unsigned long = m long long = x unsigned long long = y float = f double = d long double = e string = Ss int[] = A_i double[] = A_d vector<int> = St6vectorIiSaIiE
c++のstringへの変換について
to_stringが使えない
あまり考えずにto_stringを使おうとしたら、以下のコンパイルエラーが出た
error: ‘to_string’ is not a member of ‘std’
c++11にするとか、コンパイル時の指定が必要とか書いてある c++ - "to_string" isn't a member of "std"? - Stack Overflow
面倒なので他の方法を探してみる
stringstreamを使う
stringstreamを使った方法が見つかった
参考 - [O] C++ で int 型の値を string 型にするときは stringstream - 文字列⇔数値 - code snippets - C++11で数字→文字列はstd::to_string()、文字列→数字はstd::stoi()とかstd::stod()とか - minus9d's diary
やってみる
超適当なコード
$ cat stringToint.cpp #include <iostream> #include <string> #include <sstream> int main(void) { int a = 3; float b = 3.14; double c = 2.99792458; std::string d= "this is test"; std::string str; std::stringstream ss; ss << a; str = ss.str(); std::cout << str << std::endl; ss.str(""); ss << b; str = ss.str(); std::cout << str << std::endl; ss.str(""); ss << c; str = ss.str(); std::cout << str << std::endl; ss.str(""); ss << d; str = ss.str(); std::cout << str << std::endl; }
実行結果
$ g++ stringToint.cpp $ ./a.out 3 3.14 2.99792 this is test
vector
vectorのソート
参考: - http://blog.sarabande.jp/post/62062199465 - http://kaworu.jpn.org/cpp/std::sort
https://github.com/ludwig125/work/blob/master/src/cpp/test/sort_vector.cpp
#include <iostream> #include <algorithm> #include <vector> using namespace std; int main() { vector<int> v; v.push_back ( 3 ); v.push_back ( 4 ); v.push_back ( 1 ); v.push_back ( 2 ); std::sort(v.begin(), v.end(), std::greater<int>() ); for(vector<int>::iterator it = v.begin(); it != v.end(); it++){ cout << *it << endl; } return 0; }
実行結果
[~/git/work/src/cpp/test ] $ ./a.out 4 3 2 1 [~/git/work/src/cpp/test ] $
文字列を受け取って1文字ずつvectorに格納
#include <iostream> #include <string> #include <vector> using namespace std; int main() { string str; getline(cin,str); string tmp; // 'abcde'のような文字列を一文字ずつvectorに格納 vector<string> v; for(int i = 0; i < (int)str.size(); i++){ char ch = str[i]; cout << ch << " " << endl; // v.push_back(string(ch)); // 直接charをvectorに格納しようとしたらコンパイルエラーになったのでstringの変数に入れた tmp = ch; v.push_back(tmp); } cout << "output vector" << endl; for(vector<string>::iterator it = v.begin(); it != v.end(); it++){ cout << *it << endl; } return 0; }
c++でmsgpackを使ってみる
msgpackとは
MessagePack: It's like JSON. but fast and small.
MessagePackは、効率の良いバイナリ形式のオブジェクト・シリアライズ フォーマットです。 JSONの置き換えとして使うことができ、様々なプログラミング言語をまたいでデータを交換することが可能です。 しかも、JSONよりも速くてコンパクトです。 例えば、小さな整数値はたった1バイト、短い文字列は文字列自体の長さ+1バイトでシリアライズできます。
らしい
仕事で使う機会があったのでc++でサンプルコードを実行してみる
msgpackのインストール
MessagePack: It's like JSON. but fast and small. → C/C++ msgpack のページに従う
準備
` インストール条件
gcc >= 4.1.0 cmake >= 2.8.0
gccバージョン確認
$ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
cmake確認
なかったのでインストール
sudo apt-get install cmake $ cmake -version cmake version 2.8.12.2
msgpackのインストール
msgpackのgitはここ
$ git clone https://github.com/msgpack/msgpack-c.git $ cd msgpack-c $ cmake . $ make $ sudo make install
msgpackのバージョンを確認
- 現在のmasterのバージョンは2.1.5らしい
- msgpack-c/CHANGELOG.md at master · msgpack/msgpack-c · GitHub
msgpackのサンプルコードを実行
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
First program(単なるデータのシリアライズとデシリアライズ)
コード
以下を hello.cpp という名前で保存
#include <msgpack.hpp> #include <vector> #include <string> #include <iostream> int main(void) { // serializes this object. std::vector<std::string> vec; vec.push_back("Hello"); vec.push_back("MessagePack"); // serialize it into simple buffer. msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec); // deserialize it. msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size()); // print the deserialized object. msgpack::object obj = oh.get(); std::cout << obj << std::endl; //=> ["Hello", "MessagePack"] // convert it into statically typed object. std::vector<std::string> rvec; obj.convert(rvec); }
コンパイル
$ g++ -Ipath_to_msgpack/include hello.cpp -o hello 実行 $ ./hello ["Hello", "MessagePack"]
Streaming into an array or map(配列やマップのシリアライズとデシリアライズ)
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
ここにはシリアライズはあるが、デシリアライズの処理がないので、自分で作ってみる
$ cat stream.cpp #include <msgpack.hpp> #include <iostream> #include <string> #include <sstream> int main(void) { // serializes multiple objects into one message containing an array using msgpack::packer. msgpack::sbuffer buffer; msgpack::packer<msgpack::sbuffer> pk(&buffer); pk.pack_array(4); pk.pack(std::string("Log message ... 1")); pk.pack(std::string("Log message ... 2")); pk.pack(std::string("Log message ... 3")); pk.pack(std::string("Log message ... 4")); // serializes multiple objects into one message containing a map using msgpack::packer. msgpack::sbuffer buffer2; msgpack::packer<msgpack::sbuffer> pk2(&buffer2); pk2.pack_map(2); pk2.pack(std::string("x")); pk2.pack(3); pk2.pack(std::string("y")); pk2.pack(3.4321); // pk2.pack(4); /*---- 以下自作部分 ----*/ // unpack array msgpack::unpacked msg; msgpack::unpack(msg, buffer.data(), buffer.size()); msgpack::object obj = msg.get(); msgpack::object_array obj_array = obj.via.array; std::string str[4]; for (int i = 0; i < 4; i++) { (obj_array.ptr[i]).convert(str[i]); std::cout << "str[" << i << "]: " << str[i] << std::endl; } // unpack map msgpack::unpacked msg2; msgpack::unpack(msg2, buffer2.data(), buffer2.size()); msgpack::object obj2 = msg2.get(); msgpack::object_map obj_map = obj2.via.map; for (int i = 0; i < 2; i++) { std::string map_key; //std::cout << "key: " << obj_map.ptr[i].key; (obj_map.ptr[i].key).convert(map_key); // 以下、mapのvalの方は、intの場合とfloatの場合があるので一旦floatにconvert // してからstringに変換した float f; // obj_map.ptr[i].valはmsgpackのobject // 一旦floatにconvertしてからそれを文字列に変換した (obj_map.ptr[i].val).convert(f); std::stringstream ss; ss << f; std::cout << "key: " << map_key << " val: " << ss.str() << std::endl; // これを実行するとintは2, floatは4と表示される //std::cout << "type: " << (obj_map.ptr[i].val).type << std::endl; // 以下のようなif文で判定できるが、このプログラムでは一括してfloatに変換している //if ( (obj_map.ptr[i].val).type == msgpack::type::POSITIVE_INTEGER ) { //} } // $ g++ -Ipath_to_msgpack/include stream.cpp -o stream }
実行結果
$ g++ -Ipath_to_msgpack/include stream.cpp -o stream $ ./stream str[0]: Log message ... 1 str[1]: Log message ... 2 str[2]: Log message ... 3 str[3]: Log message ... 4 key: x val: 3 key: y val: 3.4321
上の修正は以下を参考にした
msgpackのオブジェクトとしてここを参考にした
- https://github.com/msgpack/msgpack-c/blob/master/include/msgpack/object.h#L27-L43
- 以下でobjectのtypeが定義されているらしい
MSGPACK_OBJECT_NIL = 0x00, MSGPACK_OBJECT_BOOLEAN = 0x01, MSGPACK_OBJECT_POSITIVE_INTEGER = 0x02, MSGPACK_OBJECT_NEGATIVE_INTEGER = 0x03, MSGPACK_OBJECT_FLOAT32 = 0x0a, MSGPACK_OBJECT_FLOAT64 = 0x04, MSGPACK_OBJECT_FLOAT = 0x04, #if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT) MSGPACK_OBJECT_DOUBLE = MSGPACK_OBJECT_FLOAT, /* obsolete */ #endif /* MSGPACK_USE_LEGACY_NAME_AS_FLOAT */ MSGPACK_OBJECT_STR = 0x05, MSGPACK_OBJECT_ARRAY = 0x06, MSGPACK_OBJECT_MAP = 0x07, MSGPACK_OBJECT_BIN = 0x08, MSGPACK_OBJECT_EXT = 0x09
- 注意点として、msgpackのバージョンによるのか、関数名や引数が参照渡しかポインタ渡しかなどが違うみたい
- 単純に例と同じようにやってもうまく行かなかった
User-defined classes(MSGPACK_DEFINE)
msgpack-c/QUICKSTART-CPP.md at master · msgpack/msgpack-c · GitHub
You can use serialize/deserializes user-defined classes using MSGPACK_DEFINE macro.
とある通り、ユーザ定義のクラスをMSGPACK_DEFINEというマクロを使ってシリアライズ/デシリアライズできる
$ cat msgpack_define.cpp #include <msgpack.hpp> #include <vector> #include <string> #include <iostream> class myclass { //private: // std::string m_str; // std::vector<int> m_vec; public: std::string m_str; std::vector<int> m_vec; MSGPACK_DEFINE(m_str, m_vec); myclass() { m_str = "default"; m_vec.push_back(1); m_vec.push_back(2); m_vec.push_back(3); } }; int main(void) { std::vector<myclass> vec; // add some elements into vec... vec.push_back(myclass()); // you can serialize myclass directly msgpack::sbuffer sbuf; msgpack::pack(sbuf, vec); msgpack::object_handle oh = msgpack::unpack(sbuf.data(), sbuf.size()); msgpack::object obj = oh.get(); // you can convert object to myclass directly std::vector<myclass> rvec; obj.convert(rvec); for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) { std::cout << (*it).m_str << std::endl; for(std::vector<int>::iterator m_vec_it = (*it).m_vec.begin(); m_vec_it != (*it).m_vec.end(); ++m_vec_it) { std::cout << (*m_vec_it) << std::endl; } } }
実行結果
$ g++ -Ipath_to_msgpack/include msgpack_define.cpp -o msgpack_define $ ./msgpack_define default 1 2 3
MSGPACK_DEFINEの定義
v1_1_cpp_adaptor · msgpack/msgpack-c Wiki · GitHub
ソースコードは以下 - https://github.com/msgpack/msgpack-c/blob/55b51c506fee9ce496e9b98aca33cadade681479/include/msgpack/adaptor/define_decl.hpp#L28-L42
#define MSGPACK_DEFINE_ARRAY(...) \ template <typename Packer> \ void msgpack_pack(Packer& pk) const \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_pack(pk); \ } \ void msgpack_unpack(msgpack::object const& o) \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_unpack(o); \ }\ template <typename MSGPACK_OBJECT> \ void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone& z) const \ { \ msgpack::type::make_define_array(__VA_ARGS__).msgpack_object(o, z); \ } 同じソースコードに下に以下も定義されているので、MSGPACK_DEFINE がMSGPACK_DEFINE_ARRAYに置き換わる #define MSGPACK_DEFINE MSGPACK_DEFINE_ARRAY
pythonトラブル対応
エラー
AttributeError
AttributeError: module 'json' has no attribute 'dump'
- pythonのソースコードの中でimport jsonをしていたが、このファイル自体がjson.pyという名前だったのでモジュール名とぶつかっていたらしい
- json.py → 適当な別の名前にして解決した
- 参考:Python でモジュール利用時に AttributeError が出た時はファイル名ディレクトリ名が被ってないか調べること - shouhの日記
誤ったインタプリタです: そのようなファイルやディレクトリはありません
pip3を使おうとしたらこんなエラーが
[~/git/work/src/python/memo/pandas] $ pip3 install pandas_ply /home/ludwig125/.pyenv/pyenv.d/exec/pip-rehash/pip: /home/ludwig125/.pyenv/versions/3.5.4/bin/pip3: /home/前のユーザ名/.pyenv/versions/3.5.4/bin/python3.5: 誤ったインタプリタです: そのようなファイルやディレクトリはありません
Ubuntu14.0.4でホスト名とユーザ名を変更する - ludwig125のブログ
これでユーザ名を変えてしまったせいみたい
解決できないのでpyenvごと削除して作り直す
[~] $ pyenv versions * system (set by /home/ludwig125/.python-version) 3.5.4 [~] $ pyenv uninstall 3.5.4 pyenv: remove /home/ludwig125/.pyenv/versions/3.5.4? yes [~] $ [~] $ pyenv install 3.5.4 Downloading Python-3.5.4.tar.xz... -> https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tar.xz Installing Python-3.5.4... Installed Python-3.5.4 to /home/ludwig125/.pyenv/versions/3.5.4 $ pyenv local 3.5.4で移動
これでpip3を使えるようにになった
[~] $ [~] $ pip3 --version pip 9.0.1 from /home/ludwig125/.pyenv/versions/3.5.4/lib/python3.5/site-packages (python 3.5) [~] $