GDB:包含STL容器的Pretty-Print类

时间:2017-04-20 12:52:07

标签: c++ stl gdb pretty-print gdb-python

我正在尝试为包含std ::对象的类编写一个漂亮的打印机,我也提供了自己的漂亮打印机。基本上,这就是我的C ++代码的样子:

#include <set>
#include <iostream>
#include <cassert>

class Foo {
public:
  int x;

  bool operator<(const Foo & rhs) const {
    return this->x < rhs.x;
  }
};

class FooContainer {
public:
  std::set<Foo> content;
};

int main(int argc, char **argv) {
  FooContainer c;
  Foo f1 {1};
  Foo f2 {2};
  c.content.insert(f1);
  c.content.insert(f2);

  assert(false); // hand over to gdb
}

我希望能够漂亮地打印“FooContainer”类的对象。所以,我想要漂亮的打印机看起来像这样:

class FooPrinter(object):
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "X: " + str(self.val['x'])

class FooContainerPrinter(object):
    def __init__(self, val):
        self.val = val

    def to_string(self):
        res = ""
        for foo in self.val['content']:
            res += " " + FooPrinter(foo).to_string()
        return res

然而,尝试这些,GDB给了我一个错误:

(gdb) p c 
Python Exception <class 'TypeError'> 'gdb.Value' object is not iterable: 
$7 =

看起来FooContainerPrinter只能访问std :: set的内部成员,并且不能迭代它。我会真的喜欢避免不得不遍历std :: set my后面的红黑树。有没有一个巧妙的技巧来实现这一目标?

2 个答案:

答案 0 :(得分:2)

没有什么好方法可以做到你想要的。主要问题是,漂亮的打印API有目的地保持简单(可能有点过于简单),因此它不提供可拆卸容器的可编程方式 - 它只提供打印所需的内容,有时候不那么一般。

但是,在这种情况下,一种可行的方法可能是推迟到std::set打印机。

也就是说,只需删除FooContainer打印机,然后只需编写Foo打印机即可。将使用默认gdb样式打印FooContainer,将使用libstdc ++打印机显示随附的std::set,并使用Foo打印机显示各个元素。

如果你真的想把整个内容打印成一个长字符串,那么我恐怕你不得不挖掘std::set打印机并从中提取一些代码。

答案 1 :(得分:1)

经过一番尝试,我发现了一种非常接近的方式。我基本上使用stdlib提供的默认StdSetPrinter,但我没有使用它进行打印,只是为了迭代集合。我的代码现在看起来像这样:

from libstdcxx.v6.printers import StdSetPrinter

class FooPrinter(object):
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "X: " + str(self.val['x'])

class FooContainerPrinter(object):
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return "My Foo Container"

    def children(self):
        pp = StdSetPrinter("dummy", self.val['content'])
        return pp.children()

现在,默认漂亮的印刷魔术仍然添加了一些样板(基本上它输出&#34;我的Foo容器= {...⟨漂亮的内容print ...}&#34;)但这对我来说没问题。我认为它甚至可以定义自己的children(),而是使用to_string()内部的pp.children(),从而完全控制输出字符串。

它的缺点是libstdc ++放置其默认漂亮打印机的路径需要在PYTHONPATH中。