RE: [ROOT] linking and calling comlied code at runtime

From: Philippe Canal (pcanal@popgtw.fnal.gov)
Date: Mon Oct 30 2000 - 22:11:35 MET


Hi Sven,

In this answer I will go over some possible solution to your problem.
I will also add some comments on the example you provided (those
are probably due to simplification you made).

First a very simple change, use the following main:

int main( int argc, char **argv ) {

  gSystem->CompileMacro( "/home/sas/src/ana/macros/test2.C" );
  gROOT->ProcessLine("newtask->Run();");	  
}

A more flexible way is to introduce a new top class, for example AllTasks :

// ============= AllTasks.h
#include "TNamed.h"

class AllTasks : public TNamed {
public:
  AllTasks(const char* name, const char* title = "Misc. task" ) : TNamed(name,title) {}
  virtual ~AllTasks() { }
  virtual Int_t Run() { return 0; }

  ClassDef(AllTasks,0)  // This is the interface class for tasks
};

// ============= AllTasks.C
#include "AllTasks.h"
ClassImp(AllTasks)

//  ============= Test2.C
#include <iostream.h>
#include "AllTasks.h"

int test2() {
  cout << "Here's test2!\n";
  return( 2 );
};

class MyTask : public AllTasks {
public:
  MyTask(const char* name ="standard",const char* title="A MyTask") : 
    AllTasks(name,title) {};
  Int_t Run();
  ClassDef(MyTask, 0) // This is the real working horse
};

Int_t MyTask::Run() {
  cout << "Here MyTask!\n";
  return( 2 );
};

ClassImp(MyTask)

==================== End of source files

Then you could use a main like:

int main( int argc, char **argv ) {
  gSystem->CompileMacro( "/home/sas/src/ana/macros/AllTasks.C++" );
  gSystem->CompileMacro( "/home/sas/src/ana/macros/test2.C++" );

  TClass * taskClass = gROOT->GetClass("MyTask");
  AllTasks * task = taskClass->New();
  task->Run();
}

Or from the root command line:

root [] .L AllTasks.C++
root [] .L test2.C++
root [] MyTask * task = new MyTask("fromcommandline");
root [] task->Run();
root [] SomeCompiledFunctionOnTask( task );
etc...


Now a few comments on the specific code you sent:


In the main, you wrote:

>   MyTask *task = (MyTask *)root.FindObject( "newtask" );

However, MyTask does not inherit from TNamed and stuff does not
have a name and can not be retrieved with FindObject.


In MyTask, you did not use ClassDef and ClassImp.  This allows you to use
the file as interpreted script, but also means that this class is not known
to the ROOT meta-class system (TClass, etc...) 

> I also tried the following approach:
> 
> Func_t test2 = gSystem->DynFindSymbol(
> "/home/sas/src/ana/macros/test2.so", "test2" );

I answer this last question for completness but recommend against using something
like that.
Func_t is a pointer to a function, could you cast it to 
the proper type (assuming you know it) and use it like:

	typedef int (*testfunct)();

	....
      testfunc test2 = (testfunc)gSystem->
		DynFindSymbol("/home/sas/src/ana/macros/test2.so", "test2" );
	....


Philippe Canal.	

> -----Original Message-----
> From: owner-roottalk@pcroot.cern.ch
> [mailto:owner-roottalk@pcroot.cern.ch]On Behalf Of Sven Schmidt
> Sent: Monday, October 30, 2000 9:28 AM
> To: roottalk@pcroot.cern.ch
> Subject: [ROOT] linking and calling comlied code at runtime
> 
> 
> Hi,
> 
> I'm writing an analysis program that loops over events from trees,
> performs cuts and fills histograms. Basically it's a decendant of the
> "Event.h/cxx" framework as provided in the tutorials.
> 
> In order to vary cuts I would now like to pull the cut logic from my
> event loop and put in an extra source file. In order to avoid having to
> recompile/relink for every little change I make I had the idea to
> dynamically link this file at runtime. While this works w/o problems, I
> cant't reference any implementations in the extra file, because the
> linker can't resolve the symbols that are in there.
> 
> Example:
> 
> 
> > cat test.C
> 
> #include <iostream.h>
> #include <TROOT.h>
> 
> TROOT root( "test", "Test" );
> 
> class MyTask : public TObject {
> public:
>   Int_t Run();
> };
> 
> int main( int argc, char **argv ) {
> 
>   gSystem->CompileMacro( "/home/sas/src/ana/macros/test2.C" );
>   
>   MyTask *task = (MyTask *)root.FindObject( "newtask" );
>   task->Run();
> 
> }
> 
> 
> -----------------------------------------
> 
> > cat test2.C
> 
> #include <iostream.h>
> 
> int test2() {
>   cout << "Here's test2!\n";
>   return( 2 );
> };
> 
> class MyTask : public TObject {
> public:
>   Int_t Run();
> };
> 
> Int_t MyTask::Run() {
>   cout << "Here MyTask!\n";
>   return( 2 );
> };
> 
> MyTask newtask;
> 
> 
> -----------------------------------------
> 
> On compiling I get:
> 
> /home/sas/src/ana/macros/test.C:16: undefined reference to
> `MyTask::Run(void)'
> collect2: ld returned 1 exit status
> 
> which is actually not such a big surprise. But how can I avoid it? Is
> there a way to tell the linker to ignore unreference symbols? BTW:
> platform is linux-ppc.
> 
> I also tried the following approach:
> 
> Func_t test2 = gSystem->DynFindSymbol(
> "/home/sas/src/ana/macros/test2.so", "test2" );
> 
> But how would I invoke the function? test2() in test.C won't do it and I
> couldn't find any information on Func_t in the docs.
> 
> TIA,
> Sven
> 



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:36 MET