注册专用于std :: unordered_map的gdb pretty-printer [英] Registering a gdb pretty-printer for a specialization of std::unordered_map
问题描述
我正在尝试为 std :: unordered_map
的特定专业注册漂亮打印机,但由于某些原因,它始终对 std :: unordered_map使用标准的漂亮打印机
而不是我的专用版本.
I'm trying to register a pretty-printer for a specific specialization of std::unordered_map
, but for some reason it always uses the standard pretty-printer for std::unordered_map
in gdb instead of my specialized version.
考虑以下课程
namespace ns {
class MyClass {
public:
std::string name;
int value = 0;
};
} // namespace ns
我为它定义了一个gdb漂亮打印机
I have a gdb pretty-printer defined for it as
# myprinters.py -> sourced in gdb
class MyClassPrinter:
def __init__(self, val):
self.name = val["name"]
self.val = val["value"]
def to_string(self):
return f"MyClass(name={self.name}, value={self.val})"
import gdb.printing
pp = gdb.printing.RegexpCollectionPrettyPrinter('myprinters')
pp.add_printer('MyClass', 'MyClass', MyClassPrinter)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, replace=True)
现在考虑下面的主要功能
Now consider the main function below
int main(int argc, char *argv[]) {
std::tuple<int, MyClass> mytuple{10, {"name10", 10}};
std::unordered_map<int, MyClass> mymap;
mymap.insert({10, {"name10", 10}});
mymap.insert({15, {"name15", 15}});
mymap.insert({25, {"name25", 25}});
auto myobj = MyClass{"name5", 5};
std::unordered_map<int, MyClass *> mymap2;
mymap2.insert({10, new MyClass{"name10", 10}}); // don't worry about the new
mymap2.insert({15, new MyClass{"name15", 15}});
mymap2.insert({25, new MyClass{"name25", 25}});
std::cout << "The end" << std::endl;
return 0;
}
如果在 cout
行中添加断点并打印 myobj
,我将得到 $ 7 = MyClass(name ="name5",value = 5)
符合预期.打印 mytuple
和 mymap
也是可行的,因为gdb在STL中为容器提供了漂亮的打印机.我们得到类似
If a add a breakpoint in the cout
line and print myobj
I get $7 = MyClass(name="name5", value=5)
as expected. Printing mytuple
and mymap
also works, since gdb has pretty-printers for the containers in STL. We get something like
$8 = std::tuple containing = {
[1] = 10,
[2] = MyClass(name="name10", value=10)
}
$9 = std::unordered_map with 3 elements = {
[25] = MyClass(name="name25", value=25),
[15] = MyClass(name="name15", value=15),
[10] = MyClass(name="name10", value=10)
}
但是,我实际拥有的是带有 MyClass *
而不是 MyClass
的容器,例如 mymap2
变量.打印结果
However, what I actually have are containers with MyClass*
and not MyClass
, such as the mymap2
variable. Printing that results in
$10 = std::unordered_map with 3 elements = {
[25] = 0x555555576760,
[15] = 0x555555576710,
[10] = 0x555555576650
}
这不是很有用.
对于我的特殊需要,我只需要名称" mymap2
中指向的每个 MyClass
对象的字段.然后,我为 std :: unordered_map< int,MyClass *>
创建了一个漂亮的打印机,但是我无法正确注册它(也许只是 std :: unordered_map的版本
处于优先地位,但我无法正确禁用该假设,当尝试按
For my particular needs, I only need the "name" field of each MyClass
object pointed in mymap2
. Then I created a pretty-printer for std::unordered_map<int, MyClass *>
, but I'm not able to register it correctly (maybe the version for just std::unordered_map
is taking precedence, but I could not correctly disable to test this hypothesis. I get an error when I try to disable the pretty-printer as suggested in this question).
我尝试过
class MyUnorderedMapOfMyClassPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
return "MyUnorderedMapOfMyClassPrinter"
,然后将以下行添加到定义我的漂亮打印机的python脚本中
and then added the line below to the python script defining my pretty-printers
pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<int, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)
包括新的漂亮打印机.
但是打印unordered_map不会使用我的漂亮打印机.它仍然使用来自gdb的常规 std :: unordered_map
漂亮打印机.
But printing the unordered_map does not use my pretty-printer. It still uses the regular std::unordered_map
pretty-printer from gdb.
如果我确实创建了一个新类型,例如
If I do create a new type like
class MyUnorderedMap : public std::unordered_map<int, MyClass *> {};
并为 MyUnorderedMap
注册一个漂亮的打印机,然后它就可以工作了.但是我不想创建另一个类型只是为了注册漂亮的打印机.
and register a pretty-printer for MyUnorderedMap
then it works. But I don't want to create another type just to be able to register a pretty-printer.
如何为 std :: unordered_map
的特定专业注册漂亮打印机?
How can I register a pretty-printer for a specific specialization of std::unordered_map
?
修改:我不能仅禁用 std :: unordered_map
漂亮打印机,但是我在gdb中使用 disable pretty-printer
禁用了所有漂亮打印机,然后仅通过 enable pretty-printer global myprinters
启用了我的漂亮打印机.这使我可以尝试使用正则表达式来注册我的漂亮打印机并使其与 pp.add_printer('MyUnorderedMapOfMyClassPrinter','std :: unordered_map<.*,ns :: MyClass\ *>',MyUnorderedMapOfMyClassPrinter)
(请注意最后的"*",因为我只希望它适用于 MyClass
指针).
I could not disable only the std::unordered_map
pretty-printer, but
I disabled all pretty-printers with disable pretty-printer
in gdb, and then enabled only my pretty-printers with enable pretty-printer global myprinters
. This allowed me try the regexp to register my pretty-printer and to make it work for a std::unordered_map specialization with with pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<.*, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)
(note the "*" at the end, since I only want it to work for MyClass
pointers).
有趣的是, pp.add_printer('MyUnorderedMapOfMyClassPrinter','std :: unordered_map< int,ns :: MyClass \ *>',MyUnorderedMapOfMyClassPrinter)
没有工作.我出于某种原因不得不使用.*
而不是 int
.
Interesting, pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<int, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)
did not work. I had to use .*
instead of int
to make it work for some reason.
但是,当所有漂亮打印机都启用后,标准的 std :: unordered_map
漂亮打印机仍然优先于我的专业化.如何使我的漂亮打印机优先?
However, when all pretty-printers are enabled the standard std::unordered_map
pretty printer still takes precedence over my specialization. How can I make my pretty-printer takes precedence?
为使内容易于再现,这是完整的 main.cpp
文件
For making things easily reproducible, here is the full main.cpp
file
#include <iostream>
#include <string>
#include <tuple>
#include <unordered_map>
namespace ns {
class MyClass {
public:
std::string name;
int value = 0;
};
} // namespace ns
using namespace ns;
int main(int argc, char *argv[]) {
std::tuple<int, MyClass> mytuple{10, {"name10", 10}};
std::unordered_map<int, MyClass> mymap;
mymap.insert({10, {"name10", 10}});
mymap.insert({15, {"name15", 15}});
mymap.insert({25, {"name25", 25}});
auto myobj = MyClass{"name5", 5};
std::unordered_map<int, MyClass *> mymap2;
mymap2.insert({10, new MyClass{"name10", 10}});
mymap2.insert({15, new MyClass{"name15", 15}});
mymap2.insert({25, new MyClass{"name25", 25}});
std::cout << "The end" << std::endl;
return 0;
}
和定义漂亮打印机的完整 myprinters.py
文件
and the full myprinters.py
file defining the pretty-printers
class MyClassPrinter:
def __init__(self, val):
self.name = str(val["name"])
self.val = val["value"]
def to_string(self):
return f"MyClass(name={self.name}, value={self.val})"
class MyClassPointerPrinter:
def __init__(self, val):
self.ptr = val
self.name = str(val.dereference()["name"])
self.val = val.dereference()["value"]
def to_string(self):
return f"Pointer to MyClass(name={self.name}, value={self.val})"
class MyUnorderedMapOfMyClassPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
return "MyUnorderedMapOfMyClassPrinter"
import gdb.printing
pp = gdb.printing.RegexpCollectionPrettyPrinter('myprinters')
pp.add_printer('MyClass', '^ns::MyClass$', MyClassPrinter)
# pp.add_printer('MyClass', 'MyClass\*', MyClassPointerPrinter)
# pp.add_printer('MyClass', 'MyClass.?\*', MyClassPointerPrinter)
# pp.add_printer('MyClass', 'MyClass \*', MyClassPointerPrinter)
pp.add_printer('MyUnorderedMapOfMyClassPrinter', 'std::unordered_map<.*, ns::MyClass\*>', MyUnorderedMapOfMyClassPrinter)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, replace=True)
def my_pp_func(val):
if str(val.type) == "ns::MyClass *":
return MyClassPointerPrinter(val)
gdb.pretty_printers.append(my_pp_func)
推荐答案
对我来说,问题是 gdb.current_objfile()
始终返回 None
.因此,您的漂亮打印机被注册为全局打印机,而所有标准打印机都是对象级别的.对象级漂亮打印机优先.
For me, the problem is that gdb.current_objfile()
always returns None
. Thus your pretty printer is registered as a global one, whereas all the standard ones are object level. Object level pretty-printers take precedence.
我不知道为什么,但是我无法使此功能正常工作.
I have no idea why, but I was unable to make this function work.
可以使用以下解决方法:
It is possible to use this workaround:
gdb.printing.register_pretty_printer(gdb.objfiles()[0], pp, replace=True)
这篇关于注册专用于std :: unordered_map的gdb pretty-printer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!