I am trying to create LLDB visualizers for classes in my project. The LLDB documentation is... sparse. I have an array class that stores the underlying data in a std::vector and has an extent array to describe the shape. It can also be reshaped later.
By default, the std::vector "data_" is always shown as a linear vector. I would like my provider to create a view hierarchy. In this example, the first level would be the child rows, each row expanding to a list of column values. Similar to viewing a static 2D array (i.e. double[3][2]). You can imagine extending this to N dimensions.
I can't seem to figure out how to use the lldb python object model to impose hierarchical structure onto the linear buffer in std::vector. Nothing seems to be documented, and I have been guessing in the dark for about a week. Here is a simplified example array class that I would like to create a visualizer for.
Any help is greatly appreciated!
#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;
}
As requested: The output I would like to see for the first [3][2] example might look like the following. The first level of 3 children are "rows", with a summary string of the leading elements in the row. The idea is to get a 2D view of the matrix data. Then when a row is expanded, it would be viewed as an array of column values.
LLDB potential synthetic output:
mydata
[0]
[0] = 0 <-- expanded contents
[1] = 1
[1] = {2, 3} <-- summary string of row contents. First N elements, then ...
[2] = {4, 5}
The synthetic provider examples for a simple vector implement get_child_at_index something like this, where I determined the count, value_size, and value_type in the update() method:
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
I think I can easily work this out if I could just figure out how to create an SBType to use in place of value_type when calling CreateChildAtOffset. I think I could then lay down any kind of structure that I like. However, with many shots in the dark, I couldn't figure out how to create an SBType object successfully.
Ideas? Does anyone know how to create an SBType from a string that I compose?