python - 包含双数组的 GDB 漂亮打印自定义类型
问题描述
尝试为 GDB 编写一个 Python 扩展,它能够漂亮地打印以下 C++ 类:
class Vector {
double* myElements;
unsigned int length;
}
漂亮的打印输出应该在哪里,例如。{0.1, 0.2, 0.3}
其中数组myElements
的长度为length
。
在 gdb 中,我可以简单地做,*myVec.myElements@myVec.length
但是我想创建等效的 Python 漂亮打印。
我目前的尝试如下:
class VectorPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
length = self.val['length']
elmts = self.val['myElements']
result = []
for i in range(0, length):
result.append(elmts[i])
return str(result)
class FailPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
return "Value: " + str(self.val.type)
def lookup_type(val):
if(str(val.type) == 'Vector'):
return VectorPrinter(val)
return FailPrinter(val)
gdb.pretty_printers.append(lookup_type)
然而,这只是输出:
$1 = [<gdb.Value object at 0x000000000367d470>, <gdb.Value object at 0x000000000367d4b0>, ...,
<gdb.Value object at 0x000000000367d8f0>, <gdb.Value object at 0x000000000367d930>]
解决方案
当您的类型是某种“数组”时,最好保持to_string
方法简单(不处理元素)并有一个children
方法返回一个检索元素的生成器,以及一个display_hint
方法。此display_hint
方法必须返回字符串“array”,以指示 gdb 应使用该children
方法获取元素。
该to_string
方法可以简单到只返回一个简单的字符串,例如“vector”,但我发现包含向量的大小很有用。
我为您的班级创建了以下漂亮的打印机
class VectorPrinter:
def __init__(self, val):
self.val = val
self.length = int(val['length'])
self.mem = self.val['myElements']
def to_string(self):
return f"Vector with {self.length} elements"
def next_element(self):
for i in range(self.length):
yield str(i), (self.mem + i).dereference()
def children(self):
return self.next_element()
def display_hint(self):
return "array"
请注意,该next_element
方法实际上是一个生成器,因为它使用yield
而不是返回。
但是,当我尝试使用这台漂亮的打印机时,每个元素都被打印为Value: double,
. 问题是因为FailPrinter
. 您注册漂亮打印机的方式意味着除了 Vector 类之外,其他所有内容都使用 打印FailPrinter
,包括每个单独的元素。您真的不需要(或想要)“失败”打印机。
因此,只需使用我提供的课程并注册即可
def lookup_type(val):
if(str(val.type) == 'Vector'):
return VectorPrinter(val)
gdb.pretty_printers.append(lookup_type)
让我们看看这台漂亮的打印机正在运行。考虑下面的 main.cpp 文件
class Vector {
public:
double* myElements;
unsigned int length;
public:
Vector(unsigned int length) : length(length) {
myElements = new double[length];
for (unsigned int i = 0; i < length; i++) {
myElements[i] = i;
}
}
~Vector() {
delete[] myElements;
}
};
int main(int argc, char *argv[])
{
Vector v(10);
return 0;
}
如果我们v
在 gdb 中打印,我们会得到
注意:如果您有兴趣,我已经为犰狳库中的向量、矩阵和立方体类以及std::complex
. 这些漂亮的打印机可以在这里找到。查看代码可能会帮助您创建其他漂亮的打印机。
推荐阅读
- r - 在一个数据框中将日期转换为具有不同开始日期的天数
- javascript - 如何从 ajax 调用更新数据(chart.js)
- vb.net - 如何添加派生类?
- r - 敏感性分析:如何生成多个数据集并对每个数据集进行贝叶斯回归分析?
- sharepoint - 是否可以从 PowerBI 中的 SharePoint 文件夹自动上传/合并文件?
- javascript - 将现有组件从基于类转换为基于函数时应用样式的反应问题
- azure-devops - 在 Azure 发布管道中运行 Node.js 服务器
- ios - 存档时找不到框架
- configuration - 如何在 Pimcore 的 CoreShop 中收听“确认”状态机?
- unity3d - Unity:如何访问 Android 立体后置摄像头?