GDB: Pretty-Print class 包含 STL 容器
GDB: Pretty-Print class containing STL container
我正在尝试为 class 编写一个漂亮的打印机,其中包含 std::set 个对象,我也为其提供了我自己的漂亮打印机。基本上,这就是我的 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
}
我希望能够漂亮地打印 class "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:
=
看起来 FooContainerPrinter 只能访问 std::set 的内部成员,不能迭代它。我 真的 想避免自己必须遍历那个 std::set 后面的红黑树。有什么巧妙的技巧可以实现这一目标吗?
没有什么好的方法可以完全按照您的意愿行事。主要问题是漂亮的打印 API 故意保持简单(可以说有点太简单了),因此它不提供可编程的方式来挑选容器——它只提供打印所需的内容,有时不太笼统。
但是,在这种情况下,一种可行的方法可能是遵从 std::set
打印机。
也就是干脆放下FooContainer
打印机,写个Foo
打印机就行了。 FooContainer
将使用默认的 gdb 样式打印,封闭的 std::set
将使用 libstdc++ 打印机显示,单个元素将使用您的 Foo
打印机显示。
如果您真的想将整个内容打印成一个长字符串,那么恐怕您将不得不挖掘 std::set
打印机并从中提取一些代码。
经过一番尝试,我找到了一种非常接近的方法。我基本上使用 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()
现在,默认的漂亮打印魔术仍然添加了一些样板(基本上它输出 "My Foo Container = { … ⟨ pretty-print of the contents ⟩ …}"),但这对我来说没问题。我认为它甚至可以 not 定义自己的 children(),而是在 to_string() 中使用 pp.children() 从而拥有完全控制权在输出字符串上。
它的缺点是 libstdc++ 放置其默认漂亮打印机的路径需要在 PYTHONPATH 中。
我正在尝试为 class 编写一个漂亮的打印机,其中包含 std::set 个对象,我也为其提供了我自己的漂亮打印机。基本上,这就是我的 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
}
我希望能够漂亮地打印 class "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:
=
看起来 FooContainerPrinter 只能访问 std::set 的内部成员,不能迭代它。我 真的 想避免自己必须遍历那个 std::set 后面的红黑树。有什么巧妙的技巧可以实现这一目标吗?
没有什么好的方法可以完全按照您的意愿行事。主要问题是漂亮的打印 API 故意保持简单(可以说有点太简单了),因此它不提供可编程的方式来挑选容器——它只提供打印所需的内容,有时不太笼统。
但是,在这种情况下,一种可行的方法可能是遵从 std::set
打印机。
也就是干脆放下FooContainer
打印机,写个Foo
打印机就行了。 FooContainer
将使用默认的 gdb 样式打印,封闭的 std::set
将使用 libstdc++ 打印机显示,单个元素将使用您的 Foo
打印机显示。
如果您真的想将整个内容打印成一个长字符串,那么恐怕您将不得不挖掘 std::set
打印机并从中提取一些代码。
经过一番尝试,我找到了一种非常接近的方法。我基本上使用 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()
现在,默认的漂亮打印魔术仍然添加了一些样板(基本上它输出 "My Foo Container = { … ⟨ pretty-print of the contents ⟩ …}"),但这对我来说没问题。我认为它甚至可以 not 定义自己的 children(),而是在 to_string() 中使用 pp.children() 从而拥有完全控制权在输出字符串上。
它的缺点是 libstdc++ 放置其默认漂亮打印机的路径需要在 PYTHONPATH 中。