Re: Pointer to function

Masaharu Goto (gotom@hpyiddq.jpn.hp.com)
Mon, 02 Jun 1997 10:37:33 JST


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