こんにちは、高木です。
C++からTkを使うにあたってはどうしてもTclが必要になります。今回は、Tclを使う上で一番基本となるTcl_Obj型について見ていくことにします。
昔のTclは、値にせよコマンドにせよすべて文字列として扱っていました。ところが、主にバイナリーデータを扱うためだと思うのですが、Tcl 8.0以降はTcl_Obj型を内部表現に使っています。
Tcl_Obj型は文字列のほか、整数型、浮動小数点型、リスト型などを格納できるようになっています。ユーザー定義の型を作ることもできます。
Tcl_Obj型は内部に参照カウンターを持っています。Tcl_Obj型のオブジェクトを作って、使って、すぐに破棄するならいいのですが、いろいろ持ち回る場合は参照カウンターを用いて参照状況を管理する必要があります。
Tcl_IncrRefCountマクロで参照カウンターをインクリメントし、Tcl_DecrRefCountマクロでデクリメントします。参照カウンターが0以下になればオブジェクトは破棄されます。
ところで、TclのC言語APIには、Tcl_Obj型のほかにTcl_Object型というのもあります。非常に紛らわしいのですが、これはTclOOというオブジェクト指向をTclに導入するために使う者ですのでまったく別物です。
それでは、早速Tcl_Obj型のラッパークラスを作ってみましょう。
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <tcl.h> #include <utility> namespace tcl { class obj { public: obj() : obj_(Tcl_NewObj()) { Tcl_IncrRefCount(this->obj_); } obj(const obj& src) : obj_(src.obj_) { Tcl_IncrRefCount(this->obj_); } obj(obj&& src) : obj_(src.obj_) { src.obj_ = nullptr; } ~obj() noexcept { if (this->obj_) { Tcl_DecrRefCount(this->obj_); this->obj_ = nullptr; } } obj& operator=(const obj& src) { auto t(src); swap(t); return *this; } obj& operator=(obj&& src) { auto t(std::move(src)); swap(t); return *this; } void swap(obj& other) noexcept { std::swap(this->obj_, other.obj_); } private: Tcl_Obj* obj_; }; } |
今回は最小限の内容だけにとどめておきます。デフォルトコンストラクター、コピー/ムーブコンストラクター、デストラクター、コピー/ムーブ代入演算子、あとswapメンバー関数だけを用意しています。
コンストラクターではTcl_IncrRefCountマクロで参照カウンターを増やし、デストラクターで減らしています。今回はこの程度にしておきましょう。
今回はTcl_Obj型の最小限のラッパークラスを作ってみました。これだけでは何もできませんので、次回以降はこれをもとに肉付けをしていきたいと思います。