1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/*!
\addtogroup group_function Function objects
\ingroup book_...
*/
/*!
\page page_function
\ingroup group_function
<hr><h2>Defining and initializing <code>Function</code> objects</h2>
<h4>Defining</h4>
<code>Function</code> objects need to be defined as static or global objects
otherwise they will be re-initialized every time you call the
<code>Function::init()</code> method.
\code
Function f1; // Global `Function' instance.
void f()
{
static Function f2; // Static `Function' instance.
f2.init();
}
\endcode
Each <code>Function</code> instance needs to be initialized at least once before
it can be used. There are several ways to do this all of which
use the overloaded <code>Function::init()</code> method.
When you try to use an uninitialized <code>Function</code> object,
the program will fail by default (exit with an error
message). If you don't want that then you can add a
flag to its constructor:
\code
Function f1(Function::nofail);
\endcode
<h4>Initializing</h4>
First of all, it is possible to assign the <em>current function</em> to
a <code>Function</code> object like so:
\code
void f()
{
f1.init(); // f1 represents the current function, f().
// ...
}
\endcode
If this function is a template function (or a method in
a templated class) then it is possible that it covers
more than one instance. Therefore, in the case of
a template you need to make the function object a
static instance inside the template function: this
will lead to one instance per template function
instantiation.
In order to be able to refer to it later in that case
you must use another <code>Function</code> to alias for
the static instance:
\code
template<typename T>
void f(T const& a)
{
static Function sf; // Do NOT call sf.init()!
f1.init(sf); // f1 represents all `void f<T>(T const&)'
// template function instantiations that
// ... // have been called so far.
}
\endcode
Note that in this case the <em>static</em> object must <b>not</b> be initialized!
<h4>Searches</h4>
If you need to refer to functions that are not called yet, or when
those functions are part of third party libraries, then you'll need
to use search routines. These are much slower, especially
the ones that use the demangled names; but each lookup will be done
only once.
The following examples demonstrate several ways to search
for function symbols. These initialization calls are best
put early in main() of course. All of them will print
debug output about what they are looking up and what they
found. By default they will fail when nothing is found.
\code
f1.init(Function::regexp("^int g(.*)$")); // f1 represents all functions 'g' returning an int.
f1.init(Function::exactmatch("int h(void)")); // f1 represents the function 'int h()'.
f1.init(Function::mangled("_ZTv0_n12_NSoD0Ev"); // Look up by mangled name (exact matches only).
\endcode
The \c mangled lookup is the fastest. It looks
for both, C++ as well as C functions, so you could
use it to look for C functions skipping the cpu
intensive demangling that way.
However, you can also specifically
specify that the function you are looking for has
C linkage by passing a flag to the search.
Flags are always the right-most parameter.
\code
f1.init(Function::regexp("malloc"), Function::c_linkage);
\endcode
\c regexp and \c exactmatch look only for C++ functions
by default.
<h4>Labels</h4>
It's possible to link an arbitrary
<em>label</em> (an unsigned integer constant) to a \c Function object.
This can be useful when you want to specifically mark
a \c Function temporarily; you are allowed to reassign
labels and/or remove the labels again.
For example,
\code
// Add this to debug.h.
enum function_labels {
f_x,
f_y
};
// Elsewhere...
void f()
{
f1.init(); // f1 represents the current function
f1.label(f_x); // and assign the label f_x to it.
x();
f1.label(f_y); // Change the label, setting it to f_y.
y();
f1.rmlabel();
}
\endcode
Functions x() and y() can retrieve the label set on f1,
and as such find out whether this function (f1) called x()
or y(). This might be needed when for example x() also
calls y().
<b>Important</b>: The label is not removed when you exit function f()!
You'll have to explicitely do so yourself if you want to
keep track of the fact that the current function exited
(otherwise subsequential calls to y() could think that it
still was called from f()).
*/
|