ROOT の macro で定義した関数の返り値を受け取る方法
RootTalk で教えてもらったのでメモ。
例えば MyScript.C というのがあったとして、この中に MyFunc() という関数があったとします。
MyClass MyFunc()
{
return MyClass();
}
そして、この MyScript.C を CINT に読み込みます。
int main() { (略) gROOT->LoadMacro("MyMacro.C++"); (略) }
こうすると、CINT や RINT の中では MyFunc() を呼び出せるのですが、上記の main の中でどうやって返り値を取り出せば良いのか悩みどころです。そこで、ちょっとややこしいことをすると取りだせるようになります。基本的なやり方は以下の通りです。
int main() { (略) gROOT->LoadMacro("MyMacro.C++"); MyClass ret; gInterpreter->ProcessLine(Form("*(MyClass*)%p = MyFunc();", (void*)&ret)); (略) }
言われてみると結構単純な考え方です。
もう少し具体例で考えます。TVector3 もしくは TVector3* を返す関数があったとして、これを MyMacro.C に定義します。
#include "TVector3.h" TVector3 MyFunc1() { return TVector3(1, 2, 3); } TVector3* MyFunc2() { return new TVector3(10, 20, 30); }
これを、main() の中で呼びだします。TVector3* を受け取るためには、pointer の pointer を使わないといけないので注意が必要です。
int main() { (略) gROOT->LoadMacro("MyMacro.C++"); TVector3 v1; TVector3* v2; gInterpreter->ProcessLine(Form("*(TVector3*)%p = MyFunc1();", (void*)&v1)); v1.Print(); gInterpreter->ProcessLine(Form("*(TVector3**)%p = MyFunc2();", (void*)&v2)); v2->Print(); (略) }
なんでこんな事をやる必要が出たかというと、何かの計算をするときの設定を ROOT macro 内で定義できないかと検討したためです。光線追跡をするときに、普通だったら望遠鏡の形状を text 形式で定義しておき、それを読み込んだりします。ただし、設定を読むための関数を書くのが面倒。そこで、望遠鏡の定義は ROOT の geometry で .C の中に書いておき共通の interface だけ持たせ、それを main の中で読み込めば挙動を変えられるのではないか、という発想です。