python - 包含双数组的 GDB pretty-print 自定义类型

标签 python c++ gdb

尝试编写 GDB 的 Python 扩展,它能够漂亮地打印以下 C++ 类:

class Vector {
  double* myElements;
  unsigned int length;
}

pretty-print 输出应该在哪里,例如。 {0.1, 0.2, 0.3} 其中数组 myElements 的长度为 length

在 gdb 中,我可以简单地执行 *myVec.myElements@myVec.length 但是我想创建 Python pretty-print ,它做同样的事情。

我目前的尝试如下所示:

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”,但我发现包含 vector 的大小很有用。

我已经为你的类(class)创建了以下 pretty-print

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 而不是 return。

但是,当我尝试使用这个 pretty-print 时,每个元素都被打印为 Value: double,。问题是因为 FailPrinter。您注册 pretty-print 的方式意味着除了 Vector 类之外,其他所有内容 都是使用 FailPrinter 打印的,包括每个单独的元素。你并不真的需要(或想要)一台“失败”的打印机。

因此,只需使用我提供的类并将其注册到

def lookup_type(val):
    if(str(val.type) == 'Vector'):
        return VectorPrinter(val)

gdb.pretty_printers.append(lookup_type)

让我们看看这台 pretty-print 是如何工作的。考虑下面的 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;
}

如果我们在 gdb 中打印 v,我们会得到

pretty printting vector v


注意:如果您有兴趣,我在 armadillo 中为 vector 、矩阵和立方体类创建了一些 pretty-print 库以及 std::complex。这些 pretty-print 可用here .查看代码可能会帮助您创建其他 pretty-print 。

关于python - 包含双数组的 GDB pretty-print 自定义类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58612140/

相关文章:

python - 如何使用 xapian 和 python 匹配精确的短语?

python - Python 中的连接单元测试

c++ - 为什么这个字符串到整数的转换函数要减1?

ubuntu - 无法在调试器内调用标准数学函数?

c++ - SIGSEGV : Program doesn't execute sequentially

python - 解码、小端、未压缩和 float 组

python - Mechanize 无法登录python

c++ - 找不到 -lopencv_highgui.2.4.9 的库

c++ - 检测编译时是否存在 long long

c++ - 如何使用 Eclipse 从 Windows 调试 linux C++ 程序?