简体   繁体   English

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

[英]GDB: Pretty-Print class containing STL container

I'm trying to write a pretty-printer for a class containing a std::set of objects for which I'm also supplying my own pretty printer. 我正在尝试为包含std :: set对象的类编写一个漂亮打印机,我也为此提供了自己的漂亮打印机。 Very basically, this is how my C++ code looks like: 基本上,这就是我的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
}

I want to be able to pretty-print objects of class "FooContainer". 我希望能够漂亮地打印“ FooContainer”类的对象。 So, I want pretty-printers that look somehow like these: 所以,我想要看起来像这样的漂亮打印机:

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

However, trying these, GDB gives me an error: 但是,尝试这些,GDB给我一个错误:

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

It looks like the FooContainerPrinter only has access to the internal members of a std::set, and can't iterate it. 看起来FooContainerPrinter仅有权访问std :: set的内部成员,并且无法对其进行迭代。 I would really like to avoid having to traverse the red-black-tree behind that std::set myself. 真的很想避免遍历该std :: set背后的红黑树。 Is there a neat trick to achieve this? 有一个巧妙的技巧可以实现这一目标吗?

There's no good way to do exactly what you want. 没有很好的方法来完全按照自己的意愿去做。 The main issue is that the pretty-printing API was purposely kept simple (arguably a bit too simple) and so it doesn't provide a programmable way to pick apart containers -- it only provides just what is needed for printing, which is sometimes less general. 主要问题是,漂亮的打印API故意保持简单(可以说有点太简单了),因此它没有提供可编程的方式来分离容器-它仅提供打印所需的内容,有时不太一般。

However, in this situation one viable approach might be to defer to the std::set printer. 但是,在这种情况下,一种可行的方法可能是使用std::set打印机。

That is, simply drop the FooContainer printer, and just write a Foo printer. 也就是说,只需放下FooContainer打印机,然后编写Foo打印机即可。 A FooContainer will be printed using the default gdb style, the enclosed std::set will be displayed using the libstdc++ printer, and the individual elements will be displayed using your Foo printer. FooContainer将使用默认的gdb样式进行打印,随附的std::set将使用libstdc ++打印机显示,并且各个元素将使用Foo打印机显示。

If you really want to print the entire contents as one long string, though, then I'm afraid you'll have to dig up the std::set printer and extract some code from it. 但是,如果您真的想将全部内容打印为一个长字符串,那么恐怕您必须挖掘std::set打印机并从中提取一些代码。

After some trying, I've found a way that comes very close. 经过一番尝试,我发现了一种非常接近的方法。 I'm basically using the default StdSetPrinter provided with the stdlib, but I'm not using it for printing, just for iterating the set. 我基本上使用的是stdlib随附的默认StdSetPrinter,但我没有将其用于打印,只是用于迭代集合。 My code looks like this now: 我的代码现在看起来像这样:

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

Now, the default pretty printing magic still adds some boilerplate (basically it outputs "My Foo Container = { … ⟨ pretty-print of the contents ⟩ …}") but that is fine with me. 现在,默认的漂亮打印魔术仍然添加了一些样板(基本上,它输出“ My Foo Container = {…contents内容的漂亮打印⟩…}”),但是我觉得很好。 I think it would even be able to not define an own children(), but rather use the pp.children() inside to_string() and thus have full control over the output string. 我认为它甚至可以定义自己的children(),而是使用to_string()内的pp.children()来完全控制输出字符串。

It has the drawback that the path where libstdc++ puts its default pretty printers needs to be in the PYTHONPATH. 它的缺点是libstdc ++放置其默认漂亮打印机的路径必须位于PYTHONPATH中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM