ユーザ用ツール

サイト用ツール


サイドバー

Menu

Latest

study:software:root:myclass

MyClass

Classの作成手順

自作クラスをrootのsystemに組み込むにはTObjectを継承する必要がある。このことで例えば下のような恩恵をうけることができる。

  • collectionクラスに登録できる。このことにより、
    • rootファイルに保存できるようになる
    • TTreeのBranchとして作れるようになる
    • Drawメソッドを継承できる
  • instrospection(クラスの情報を参照する機能)を継承できる

もちろん、こうした機能を組み込まず、一般的なc++のクラスを定義することもできる。その場合はここに書かれていることは気にしなくていい。

ソースファイルを用意する

例として、下のようなクラスを作ろう

#ifndef __MYCLASS__
#define __MYCLASS__

#include <TObject.h>
#include <iostream>

class MyClass : public TObject
{
public:
    MyClass(); //デフォルトコンストラクタは必須
    int Get();
    void Set(int);
    ClassDef(MyClass,1);
protected:
    int f;
};

#endif

#include "MyClass.h"
#include <TObject.h>
#include <iostream>

ClassImp(MyClass)

MyClass::MyClass() : f(0){
  //デフォルトコンストラクタでメンバ変数にメモリ確保をしてはいけない、らしい・・・
};

int MyClass::Get(){
  return f;
};

void MyClass::Set(int a){
  f = a;
};

ポイントは

  • TObject又はそれを継承したクラスを継承すること
  • ClassDefの行を追加すること
    追加するのは、publicでもprivateでもどちらでもいい。ClassDefの第二引数はclassのversionでclassの定義を変更する度に増やす。もしもI/Oの機能をつける必要がないならば0にする。
  • デフォルトコンストラクタ又はI/Oコンストラクタ(?)を作ること
    ファイルを開いたときに、保存されていたオブジェクトを初期化するので、引数なしに実行されるコンストラクタが必要みたい。
    もう一つ注意点としてはデフォルトコンストラクターでnewしてはいけない。ファイルが読み込まれたときに、メモリーリークが起きる。
  • クラスの実装にはClassImpを入れる

ClassDef、ClassImpは$ROOTSYS/core/base/inc/Rtypes.hでdefineされた関数マクロ。

(必須)Dictionaryを作る

rootで自作クラスを使用するためにはDictionaryにクラスを登録する必要がある(?)。

コンパイルする場合

まず次のようなファイルを生成する。

#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyClass+;
#endif

さきほど作成したクラスのヘッダーMyClass.hとLinkDef.hを使い、下のようにコマンドすると、MyClassDict.cxxが生成される。

rootcint -f MyClassDict.cxx -c MyClass.h LinkDef.h

ここでLinkDef.hはコマンドの最後にくる必要がある。

あとはMyClassDict.cxxと一緒にクラスの実装コードを普通にコンパイルすればいい。

g++ `root-config --cflags --libs` -shared MyClassDict.cxx MyClass.cxx -o libmyclass.so

なにかわかっているように書いてますが、pragmaの意味は全然知りません。

ACLiCを使う場合

ACLiCを使う場合はheaderの最後にpragma statementを加えるだけでいい。らしい。

#ifndef __MYCLASS__
#define __MYCLASS__

#include <TObject.h>
#include <iostream>

class MyClass : public TObject
{
public:
    MyClass();
    int Get();
    void Set(int);
    ClassDef(MyClass,1);
protected:
    int fConst;
};

#endif

#ifdef __MAKECINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyClass+;
#endif

あとは普通にACLiCでコンパイルすればいい。

[ ] .L MyClass.cxx+

__CINT__はCINT(インタープリター)とrootcint(Dictionaryのgenerator)両方でdefineされているが、__MAKECINT__はrootcintのみでdefineされている。すなわち上のpragma statementはインタープリターでは無視される

cintの場合

cintでマクロを読ませる場合はDictionaryを作らずとも自作クラスが使用可能(理由は理解できてない)。

ただし、そのクラスをファイルに保存しても、なぜかクラスの種類はTObjectとして保存されてしまう。

いまいちDictionaryの仕組みが理解できていない。

(任意)rootmapを作る

http://root.cern.ch/root/Version516.news.html

rootでは例えばTH1などのクラスを使用するときにライブラリをリンクする必要はない。これはクラスを使用するときに自動的にライブラリを読み込むという仕組みをとっているからである。

自作したクラスについてもライブラリを自動的に読み込むようにするにはrootmapを作る必要がある。

rootmapはクラスとライブラリとの対応関係を記述したファイルで、$ROOTSYS/libに.rootmap拡張子のファイルがおいてあるのが確認できると思う。

この作業は面倒だし、わざわざこんなことしなくても、rootlogonで最初にライブラリを読み込めば全く問題ない


作り方は例えば、myclassのライブラリがlibmyclass.soで更にlibHist.soに依存している場合は以下のようにする。

rlibmap -f -o $lib/libmylib.rootmap -l $lib/libmyclass.so -d libHist.so -c $include/Linkdef.h

  • $lib、$inclucdeというのはライブラリとヘッダのあるディレクトリ
  • rootのクラスがどのライブラリを必要としているかはクラスリファレンスを見ればわかる


libmylib.rootmapを見てみると下のような単純なファイルであることがわかる。

Library.MyClass:                            libmyclass.so libHist.so

なので、自分で直接編集して作ってもいいと思う。

スコープ解決演算子::は@@に変える(std::vectorはstd@@vectorになる)

study/software/root/myclass.txt · 最終更新: 2013/12/29 22:35 by kamo

ページ用ツール