GDB довольно печатный пользовательский тип, содержащий двойной массив - PullRequest
0 голосов
/ 29 октября 2019

Попытка написать расширение Python для GDB, которое способно печатать следующий класс 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>]

1 Ответ

2 голосов
/ 30 октября 2019

Когда ваш тип является неким «видом массива», лучше сохранить метод to_string простым (без обработки элементов) и иметь метод children, который возвращает генератор, который извлекает элементы, а такжеdisplay_hint метод. Этот метод display_hint должен возвращать строку "массив", чтобы указать, что GDB должен использовать метод children для получения элементов.

Метод to_string может быть таким же простым, как просто возвращение простой строки, такой как «вектор», но я считаю полезным включить размер вектора.

Я создал следующееpretty-printer для вашего класса

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.

Однако, когда я пытался использоватьНа этом симпатичном принтере каждый элемент был напечатан как Value: double,. Проблема из-за FailPrinter. То, как вы зарегистрировали симпатичные принтеры, означает, что за исключением класса Vector, все остальное печатается с использованием FailPrinter, включая каждый отдельный элемент. Вам не нужен (или не нужен) принтер «Fail».

Поэтому просто используйте предоставленный мною класс и зарегистрируйте его как

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, мы получим

pretty printting vector v


Примечание : Если вам интересно, я создал несколько симпатичных принтеров для векторных, матричных и кубических классов в библиотеке armadillo , а также для std::complex. Эти симпатичные принтеры доступны здесь . Просмотр кода может помочь вам создать другие красивые принтеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...