Как написать синтетический провайдер LLDB для фасонного представления данных std::vector
Я пытаюсь создать визуализаторы LLDB для классов в моем проекте. Документация LLDB... скудная. У меня есть класс массива, который хранит базовые данные в std::vector и имеет массив экстентов для описания формы. Это может также быть изменено позже.
По умолчанию std::vector "data_" всегда отображается как линейный вектор. Я хотел бы, чтобы мой поставщик создал иерархию представлений. В этом примере первым уровнем будут дочерние строки, каждая строка расширяется до списка значений столбцов. Аналогично просмотру статического 2D-массива (т. Е. 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 из строки, которую я составить?
1 ответ
Я предполагаю, что вы уже просмотрели: 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 для создания типов через лязг (как мы делаем внутри), это ваш единственный подход
Не уверен, что это поможет, но можно найти существующие типы
target = lldb.debugger.GetSelectedTarget()
type_list = target.FindTypes('base::Value')
если вы хотите создать своего ребенка с существующим типом, это может помочь.