Я пытаюсь создать визуализаторы LLDB для классов в моем проекте. Документация LLDB … скудная. У меня есть класс массива, который хранит базовые данные в std :: vector и имеет массив экстентов для описания формы. Это может также быть изменено позже.
По умолчанию std :: vector «data_» всегда отображается как линейный вектор. Я хотел бы, чтобы мой поставщик создал иерархию представлений. В этом примере первым уровнем будут дочерние строки, каждая строка расширяется до списка значений столбца. Аналогично просмотру статического двумерного массива (то есть double [3] [2]). Вы можете представить себе расширение этого до N измерений.
Я не могу понять, как использовать объектную модель Python lldb для наложения иерархической структуры на линейный буфер в std :: vector.
Кажется, ничего не задокументировано, и я гадал в темноте около недели. Вот упрощенный пример класса массива, для которого я хотел бы создать визуализатор.
Любая помощь очень ценится!
#include <vector>
#include <cassert>
template <typename T>
class myarray {
int extent_[2];
std::vector<T> data_;
public:
myarray(int r, int c, const T* data) {
extent_[0] = r;
extent_[1] = c;
data_.resize(r * c);
for(size_t i = 0; i < data_.size(); ++i) data_[i] = data[i];
}
void reshape(int r, int c) {
assert(r * c == data_.size());
extent_[0] = r;
extent_[1] = c;
}
};int main(int argc, const char * argv[])
{
double initdata[6] = { 0, 1, 2, 3, 4, 5 };
myarray<double> mydata(3, 2, initdata);
mydata.reshape(1, 6);
return 0;
}
По запросу: вывод, который я хотел бы увидеть для первого примера [3] [2], может выглядеть следующим образом. Первый уровень из 3 дочерних элементов — это «строки» со сводной строкой ведущих элементов в строке. Идея состоит в том, чтобы получить 2D-представление данных матрицы. Затем, когда строка раскрывается, она будет рассматриваться как массив значений столбцов.
Потенциальная синтетическая продукция LLDB:
mydata
[0]
[0] = 0 <-- expanded contents
[1] = 1
[1] = {2, 3} <-- summary string of row contents. First N elements, then ...
[2] = {4, 5}
Примеры синтетического провайдера для простого вектора реализуют get_child_at_index примерно так, где я определил count, value_size и value_type в методе update ():
def get_child_at_index(self,index):
logger = lldb.formatters.Logger.Logger()
logger >> "get_child_at_index: " + str(index)
if index < 0: return None;
if index >= self.count: return None;
try:
offset = index * self.value_size
return self.data.CreateChildAtOffset('['+str(index)+']',offset,self.value_type)
except:
return None
Я думаю, я мог бы легко решить это, если бы я мог просто выяснить, как создать SBType для использования вместо value_type при вызове CreateChildAtOffset. Я думаю, что я мог бы тогда создать любую структуру, которая мне нравится. Однако, имея много снимков в темноте, я не мог понять, как успешно создать объект SBType.
Идеи? Кто-нибудь знает, как создать SBType из строки, которую я составить?
Я предполагаю, что вы уже просмотрели: http://lldb.llvm.org/varformats.html
IIUC, что вы хотите сделать, это отобразить элементы вектора в более иерархическом формате.
Это довольно интересная задача, для которой вам, вероятно, придется создавать свои собственные типы данных — что-то, для чего, я не думаю, у нас есть большая поддержка в нашем публичном API в настоящее время.
В качестве обходного пути, вы, конечно, можете запустить выражение, которое генерирует структуру, которая вас интересует, и удерживать ее — однако это будет медленно.
В вашем примере, какой именно вид вы хотели бы получить? Такой пример информации может быть полезен для выяснения более подробной информации.
РЕДАКТИРОВАТЬ: В настоящее время LLDB не позволяет создавать новые типы через общедоступный API. То, что вы можете сделать, чтобы получить SBType вашего собственного создания, это использовать синтаксический анализатор выражений, как в этом примере:
x = lldb.frame.EvaluateExpression("struct foo { int x; }; foo myfoo = {12}; myfoo")
data = lldb.SBData.CreateDataFromSInt32Array(lldb.eByteOrderLittle,8,[24])
x_type = x.GetType()
myOtherFoo = x.CreateValueFromData("myOtherFoo",data,x_type)
print myOtherFoo
OUTPUT: (foo) myOtherFoo = (x = 24)
Это будет довольно медленно, особенно если вы не кешируете требуемый тип foo (который из вашего примера выглядит как T [2] для аргумента шаблона T) — но пока LLDB не имеет SB API для создания типов через лязг (как мы делаем внутри), это ваш единственный подход
Других решений пока нет …