Re: CINT and compiled code

From: Masaharu Goto (MXJ02154@nifty.ne.jp)
Date: Sun Mar 05 2000 - 15:02:34 MET


Hello Rooters,

I come back from my trip and ready to answer some of your questions.
It seemed like there were 2 questions regarding interpreted and compiled
code relationship.

 1) How to call interpreted function from compiled code
 2) Can interpreted class inherit from compiled class

The classic answer to this is quoted by Rene already.  I'd like to
offer old but not advatised cint functionality , that is "STUB" 
dictionary generation.  With this, you can do both 1) and 2) 
in some sense.  I will explain this using an example.

# t350.dll  STUB class/function definition
  STUB class/function is a partly compiled class/function. Basically, you
 compile only interface of specific class or function and let interpreter
 interpret definition of member function or global function.

  There are 4 files in this example.
    t350.h   : header for precompiled class/function
    t350.cxx : source for precompiled class/function
    t350s.h  : header for STUB class/function interface
    t350s.cxx: interpreted source file

  There are 2 classes,
    class a; // precompiled class
    class b : public a; // interface only is compiled, member functions are 
                        // interpreted
  Class a and b have virtual function f(). a::f() and b::f() are resolved
  by compiler's VTBL mechanism.  Cint generates dummy for b::f() which calls
  interpreted b::f(). If you are curious, pllease look into generated 
  dictionary G__cpp_t350.cxx. 

  There are 4 global functions,
    main()    : interpreted main function (t350s.cxx)
    test()    : precompiled function (t350.cxx)
    g()       : interface is precompiled and definition is interpreted.
                Cint generates dummy g() which calls interpreted g(). If you
                are curious, please look into generated dictionary.
    scanall() : precompiled function (t350.cxx)

  Remarkable things here are

   1) interpreted funciton g() is directly used in copiled code test()
   2) virtual function resolution is done in mixed interpreted/compiled
      code environment in scanall().


This functionality has been implemented several years ago. There is a 
bug in cint and you can not use it with current version. So you can not
run it with cint5.14.32 or older. I will fix the bug in cint5.14.33.

Thank you
Masaharu Goto

----------------------------------------------------------------------
makecint/cint command

 $ makecint -mk maket350 -dl t350.dll -H t350.h -i++ t350s.h -C++ t350.cxx
 $ make -f maket350
 $ cint t350s.cxx
 a::f()
 b::f()
 b::f()
 a::f()

----------------------------------------------------------------------
// t350.h ,  precompiled class header file
#ifndef T350_H
#define T350_H

#include <stdio.h>

class a {
 public:
  int x;
  virtual void f() {printf("a::f()\n");}
};

void scanall(a** obj,int n) ;
void test() ;

#endif

----------------------------------------------------------------------
// t350.cxx , precompiled class/function definition
#include "t350.h"
extern void g();

void scanall(a** obj,int n) { // compiled
  for(int i=0;i<n;i++) {
    // precompiled a::f() or interpreted b::f() will be called
    obj[i]->f(); 
  }
}

void test() { // compiled
  g(); // interpreted function g() called from compiled code
}

----------------------------------------------------------------------
// t350s.h , stub definition for partly compiled and partly interpreted class
#ifndef T350S_H
#define T350S_H

#include "t350.h"

class b : public a { // class b definition precompiled 
 public:
  int y;
  void f(); // body of b::f() is interpreted
};

void g(); // g() is interpreted

#endif

----------------------------------------------------------------------
// t350s.cxx , interpreted source

#include "t350.dll"

void g() { // stub of g() is precompiled, but body is interpreted
  a* obj[4];
  obj[0] = new a;
  obj[1] = new b;
  obj[2] = new b;
  obj[3] = new a;
  scanall(obj,4);
}

void b::f() { // class b interface is precompiled, but b::f() is interpreted
  printf("b::f()\n");
}

main() {
  test();
}

// Operation of this program
//
//  main()      -> test()   -> g()         -> scanall() -> a::f()
//  interpreted    compiled    interpreted    compiled    virtual-intp/com
//  t350s.cxx      t350.cxx    t350s.cxx      t350.cxx    t350.cxx/t350s.cxx

----------------------------------------------------------------------


>
>Anton,
>You can read the following extract from the CINT FAQ at:
>    http://root.cern.ch/root/Cint.phtml?faq
>I understand from Masa that inheriting from a compiled class
>could be implemented in the medium long term. This is highly
>machine/compiler
>dependent.
>Note that this limitation can be removed if you use the script compiler.
>I posted an example last week.
>
>Rene Brun
>
>
>############################################################################
># Can I inherit precompiled class from an interpreted class?
># Virtual function sometimes does not work properly.
>
> Cint supports class inheritance and virtual function calls in almost
>full
> C++ spec both within interpreted classes and precompiled classes.   But 
> there is fundamental difficulty in mixing interpreted/precompiled
>virtual 
> functions.
>
> You could inherit precompiled class from an interpreted class, however, 
> virtual function calls do not work properly. Every C++ compiler has
> proprietary Virtual Function Table format which is heavily
>implementation
> dependent.  It is impossible for cint to match VTBL format of every C++
> compiler. Cint has its'own virtual function resolution mechanism. So, 
> virtual function or virtual base class can only be resolved within 
> interpreted classes or precompiled classes. 
>
> There exist other C++ interpreter which allows virtual function
>resolution
> accross the interpreted/precompiled class boundary. But they severly 
> sacrifice portability among different OS and compiler. Cint does not do 
> this because portability is the primary importance to its concept.
>
> There is another case that virtual function of a precompiled class
> does not work properly. If you call virtual function of a precompiled
> class with scope operator, polymorphic resolution should be disabled
> and given specific function should be called. However in cint, you
> can not disable polymorphic resolution of a precompiled virtual
>function.
> This leads to calling wrong function if base and derived classes are
> both precompiled.
>
>Anton Fokin wrote:
>> 
>> Hi,
>> 
>> Another stupid question. CINT macro classes can not be inherited from
>> compiled classes. That's pity but true because of the different virt tables
.
>> (By the way, is there any thoughts that this will every be possible?) Is
>> there a way to substitute (overload) a function from compiled code in CINT
>> macro? Or the only way to work with a user defined function is via
>> SetFCN(void (*fcn)) as it is done in TMinuit?
>> 
>> Best,
>> Anton



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