Somewhat related to my previous question here
Is there a way to get the calling Object from within a function or method in d?
example:
class Foo
{
public void bar()
{
auto ci = whoCalledMe();
// ci should be something that points me to baz.qux, _if_ baz.qux made the call
}
}
class Baz
{
void qux()
{
auto foo = new Foo();
foo.bar();
}
}
Questions:
whoCalledMe
exist? and if so, what is it called?Alternatively;
debug_backtrace
?To expand on what CyberShadow said, since you can get the fully qualified name of the function by using __FUNCTION__
, you can also get the function as a symbol using a mixin:
import std.stdio;
import std.typetuple;
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
alias callerFunc = TypeTuple!(mixin(func))[0];
static assert(&caller == &callerFunc);
callerFunc(); // will eventually overflow the stack
}
void caller()
{
callee();
}
void main()
{
caller();
}
The stack will overflow here since these two functions end up calling each other recursively indefinitely.
It's not directly possible to get information about your "caller". You might have some luck getting the address from the call stack, but this is a low-level operation and depends on things such as whether your program was compiled with stack frames. After you have the address, you could in theory convert it to a function name and line number, provided debugging symbols are available for your program's binary, but (again) this is highly platform-specific and depends on the toolchain used to compile your program.
As an alternative, you might find this helpful:
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
writefln("I was called by %s, which is in %s at line %d!", func, file, line);
}
void caller()
{
// Thanks to IFTI, we can call the function as usual.
callee();
}
But note that you can't use this trick for non-final class methods, because every call to the function will generate a new template instance (and the compiler needs to know the address of all virtual methods of a class beforehand).
Finding the caller is something debuggers do and generally requires having built the program with symbolic debug information switches turned on. Reading the debug info to figure this out is highly system dependent and is pretty advanced.
The exception unwinding mechanism also finds the caller, but those tables are not generated for functions that don't need them, and the tables do not include the name of the function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With