大阪市中央区 システムソフトウェア開発会社

営業時間:平日09:15〜18:15
MENU

Tclのラッパーライブラリ(オブジェクト編)

著者:高木信尚
公開日:2019/07/25
最終更新日:2019/07/25
カテゴリー:技術情報

高木です。おはようございます。

前回はTclインタープリタ、すなわちTcl_Interp型の扱い方について基本的なところを決めました。
今回はTclのデータを扱うTcl_Obj型の扱い方について考えていきたいと思います。

昔のTclはデータは何でもかんでも文字列として扱っていました。
しかし、そのやり方はレガシーなので、現在はTcl_Obj型を使ってデータを扱います。
より正確にいうと、Tcl_Obj型へのポインタを使ってデータを操作することになります。

Tcl_Objオブジェクトの構築は、Tcl_NewObj関数をはじめ、いくつかの関数を使って行います。
Tcl_Objは内部的に動的な型を持っているので、その動的な型にあわせて構築方法が異なります。
たとえば、整数であればTcl_NewIntObj関数、浮動小数点数であればTcl_NewDoubleObj関数、論理値であればTcl_NewBooleanObj関数、文字列であればTcl_NewStringObj関数、Unicode文字列であればTcl_NewUnicodeObj関数といった具合です。

Tcl_Obj型は内部に参照カウンタを持っています。
参照を増やすにはTcl_IncrRefCount関数を、参照を減らすにはTcl_DecrRefCount関数を呼び出します。
どこからも参照されなくなれば、その時点でTcl_Objオブジェクトは解体されます。
今回作成するラッパーでは、この参照カウンタの増減を自動化したいと思います。

ざっくりとしたコードは次のようになります。

namespace tcl
{
  class obj
  {
    public:
      obj(Tcl_Obj* handle)
        : handle_(handle)
      {
        Tcl_IncrRefCount(this->handle_);
      }
      obj()
        : obj(Tcl_NewObj())
      {
      }
      obj(obj const& src)
        : obj(src.handle_)
      {
      }
      obj(int value)
        : obj(Tcl_NewIntObj(value))
      {
      }
      obj(char const* s, int n = -1)
        : obj(Tcl_NewStringObj(s, n))
      {
      }
      ~obj()
      {
        Tcl_DecrRefCount(this->handle_);
        this->handle_ = nullptr;
      }

      obj& operator=(obj const& src)
      {
        obj t(src);
        swap(t);
        return *this;
      }

      void swap(obj& other)
      {
        std::swap(this->handle_, other.handle_);
      }
    private:
      Tcl_Obj* handle_;
  };
}

まだほとんど中身がなくてスカスカですが、最初はこんなもんです。

ところで、TclにはTcl_Obj型のほかにTcl_Object型というのもあります。
非常に紛らわしいですね。
以前はTcl_Object型というのはなかったのですが、OOTclが取り込まれた時点で登場したようです。
今回作るクラスもobjectクラスとしてもいいのですが、Tcl_Object型のラッパーだと誤解を与えては嫌なので、あえてobjクラスとしました。

    上に戻る