在d中获取调用对象或方法

时间:2013-08-13 13:56:23

标签: d

my previous question here

有些相关

有没有办法从d?

中的函数或方法中获取调用Object

示例:

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();
    }
}

问题:

  1. 是否存在whoCalledMe之类的内容?如果是这样,它叫什么?
  2. 如果确实存在,可以在编译时使用(在模板中),如果存在,可以如何使用?
  3. 可替换地;

    1. 是否可以在运行时访问调用堆栈?喜欢php的debug_backtrace

3 个答案:

答案 0 :(得分:5)

要扩展CyberShadow said,因为您可以使用__FUNCTION__获取函数的完全限定名称,您还可以使用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();
}

堆栈将在这里溢出,因为这两个函数最终会无限递归地相互调用。

答案 1 :(得分:4)

无法直接获取有关“来电者”的信息。你可能有幸从调用堆栈获取地址,但这是一个低级操作,取决于你的程序是否使用堆栈帧编译。获得地址后,理论上可以将其转换为函数名和行号,前提是调试符号可用于程序的二进制文件,但(再次)这是高度特定于平台的,并且取决于用于编译程序的工具链

作为替代方案,您可能会发现这有用:

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();
}

但请注意,您不能将此技巧用于非final类方法,因为每次调用该函数都会生成一个新的模板实例(并且编译器需要事先知道类的所有虚方法的地址)

答案 2 :(得分:2)

查找调用程序是调试程序所做的事情,通常需要在打开符号调试信息开关的情况下构建程序。阅读调试信息以解决这个问题是高度依赖系统的,而且非常先进。

异常展开机制也可以找到调用者,但是不为不需要它们的函数生成那些表,并且这些表不包含函数的名称。