目次

MyClass

Adding Your Class to ROOT: ClassDef

15 Adding a Class

ACLiC - The Automatic Compiler of Libraries for CINT

全ては TObject から - Dis45 ユーザーのための ROOT 入門

Classの作成手順

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

もちろん、こうした機能を組み込まず、一般的な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;
};

ポイントは

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


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

Library.MyClass:                            libmyclass.so libHist.so

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

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