Re: Pointer to function

From: Masaharu Goto (gotom@hpyiddq.jpn.hp.com)
Date: Mon Jun 02 1997 - 03:37:33 MEST


Hello Victor,

 There is a wayt to deal with pointer to funciton is a compiler environment
 I picked up related part from ny Book draft for English. Example code is 
 in the cint source code package demo/makecint/p2f/ directory.

 Fons, will you put this information on the ROOT FAQ?

Masaharu Goto

=========================================================================
G__isinterpretedp2f()

int G__isinterpretedp2f(void *p2f)

 Because the interpreter environment and C/C++ compiler has different 
processing system, special care is needed to deal with a pointer to function
in a compiled code. When pointer to function is evaluated in interpreter
environment, it returns either 1) pointer to an interpreted function, 2)
pointer to an interface method of a compiled global function, 3) pointer to
a true compiled funcion, or 4) pointer to a bytecode function. 
G__isinterpretedp2f() judges which of above case is the given pointer.
Return value is shown in a table below.

 This funciton is only valid for user specific precompiled global functions.
ANSI C library functions that are already built-int to CINT body will always
return G__UNKNOWNFUNC, however value is a true pointer to function.

 It is unneccessary to use G__isinterpretedp2f() API in interpreter environment
because cint will automatically distinguish between the pointer and handle it
properly.

 +--------------------------------------------------------------------------+
 | G__UNKNOWNFUNC             | 0 | Unknown pointer which does not exist in |
 |                            |   | the cint global function table          |
 +----------------------------+---+-----------------------------------------+
 | G__INTERPRETEDFUNC         | 1 | Pointer to an interpreted function      |
 |                            |   |                                         |
 +----------------------------+---+-----------------------------------------+
 | G__COMPILEDINTERFACEMETHOD | 2 | Pointer to an interface method of user  |
 |                            |   | embedded precompiled global function    |
 +----------------------------+---+-----------------------------------------+
 | G__COMPILEDTRUEFUNC        | 3 | Pointer to a true compiled function     |
 |                            |   |                                         |
 +----------------------------+---+-----------------------------------------+
 | G__BYTECODEFUNC            | 4 | Pointer to a bytecode function that is  |
 |                            |   | optimized by cint                       |
 +--------------------------------------------------------------------------+
                Table  Return value of G__isinterpretedp2f()


==========================================================================
G__p2f2funcname()

char* G__p2f2funcname(void* p2f)

 G__p2f2funcname() returns name of a function from a given pointer to 
function.
This function is only valid for user embedded or user interpreted global
functions.
If this function is used on ANSI C library function or CINT API function,
return value is always (char*)NULL.


  SEE ALSO G__interpretedp2f() 

==========================================================================


COMPLETE EXAMPLE:

   $ makecint -mk Makefile -o DoP2f -H compiled.h -C++ compiled.C 
    -I$CINTSYSDIR/src -I$CINTSYSDIR
   $ make
   $ DoP2F interpreted.C

List6.16===================================================================
    1  // compiled.h
    2  int f1(char* a,double b);
    3  int f2(char* a,double b);
    4  int DoFCN(void *p2f,char* a,double b) ;
========================================================================

List6.17===================================================================
    1  // compiled.C
    2  int f1(char* a,double b) { /* something */ }
    3  int f2(char* a,double b) { /* something */ }
    4
    5  #include <iostream.h>
    6  #include "Api.h"   // -I$CINTSYSDIR/src -I$CINTSYSDIR
    7
    8  int DoFCN(void *p2f,char* a,double b) {
    9    char *fname;
   10    // reconstruct function name
   11    fname=G__p2f2funcname(p2f);
   12    if(fname) {
   13      G__ClassInfo globalscope;
   14      G__MethodInfo method;
   15      long dummy;
   16      // resolve function overloading
   17      method=globalscope.GetMethod(fname,"char*,double",&dummy);
   18      if(method.IsValid()) {
   19        int (*p)(char*,double);
   20        char temp[200];
   21        int result;
   22        // get pointer to function again after overloading resolution
   23        p2f=method.PointerToFunc();
   24        // check what kind of pointer is it
   25        switch(G__isinterpretedp2f(p2f)) {
   26        case G__INTERPRETEDFUNC: // reconstruct function call as string
   27          sprintf(temp,"%s(%ld,%g)",(char*)p2f,a,b);
   28          result=G__int(G__calc(temp));
   29          break;
   30        case G__COMPILEDINTERFACEMETHOD: // using interface method
   31          G__CallFunc func;
   32          func.SetFunc((G__InterfaceMethod)p2f);
   33          func.SetArg((long)a);
   34          func.SetArg((double)b);
   35          result=func.ExecInt((void*)NULL);
   36          break;
   37        case G__COMPILEDTRUEFUNC: // using true pointer to function
   38          result=(*p2f)(a,b);
   39          break;
   40        case G__BYTECODEFUNC: // bytecode version of interpreted func
   41          G__CallFunc func;
   42          func.SetBytecode((struct G__bytecodefunc*)p2f);
   43          func.SetArg((long)a);
   44          func.SetArg((double)b);
   45          result=func.ExecInt((void*)NULL);
   46          break;
   47        case G__UNKNOWNFUNC: // this case will never happen
   48          result=(*p2f)(a,b);
   49          break;
   50        }
   51        cout << "result=" << result << endl;
   52        return(result);
   53      }
   54      else {
   55        cerr << "no overloading parameter matches" << endl;
   56      }
   57    }
   58    else {
   59      cerr << "unknown pointer to function" << endl;
   60    }
   61    return(-1);
   62  }
========================================================================


List6.18===================================================================
    1   /* interpreted.C */
    2   int f3(char* a,double b) { /* something */ }
    3
    4   main() {
    5     DoFCN(f1,"This calls precompiled f1()",1.23);
    6     DoFCN(f2,"This calls precompiled f2()",4.56);
    7     DoFCN(f3,"This calls interpreted f3()",7.89);
    8   }
========================================================================





> I have a question about pointer to function.
> 
> Simple example.
> 
> #include <stdio.h>
> int ff(int (*fptr)(const char *txt),const char *txt) {
>   (*fptr)(txt);
>   return 0;
> }
> int aaa(const char *txt){ printf(txt); return 0;}
> 
> root [0] .L ff.C
> root [1] ff(aaa,"AAAA called\n");
> AAAA called
> root [2] ff(printf,"PPPP called\n");
> PPPP called
> 
> Everything OK. Somehow CINT distinguishes pointer to 
> CINT function (aaa) from pointer to C++ function (printf)
> and works well.
> 
> But when ff.C linked to ROOT, then
> it still works with C++ function (printf) and does not
> work anymore with CINT function. It is clear, that C++ does not understand
> pointer to CINT function.
> 
> Questions:
> 
>  1. Is it possible to call or execute CINT function from C++ code?
>     By pointer or by name or ...
> 
>  2. Is it possible by value of pointer to understand does it pointed
>     out to C++ or to CINT function being inside C++ (not CINT) function?
> 
> Victor



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:26:19 MET