Я ищу подходящий способ отображения UUID через NatVis в VS2012
Я ищу подходящий способ отображения UUID через NatVis в VS2012. Мой собственный тип uuid использует UUID big-endian внутри, поэтому приведение к GUID * не работает, поскольку GUID использует little-endian в Windows. Поэтому я всегда вижу искаженный uuid.
Кроме того, любой спецификатор формата в Natvis выглядит не очень хорошо, потому что я не могу избавиться от 0x в выходе при использовании шестнадцатеричной нотации. Любые идеи?
Ответы
Ответ 1
Здесь более компактная версия решения ComicSansMS. Вместо этого я использую структуру SHA1 и визуализатор.
struct SHA1 { char hash[20]; };
namespace natvis
{
struct x4lo { unsigned __int8 v : 4; unsigned __int8 _ : 4; };
struct x4hi { unsigned __int8 _ : 4; unsigned __int8 v : 4; };
struct x8 { unsigned __int8 _; };
struct x32 { __int32 _; };
}
natvis
<Type Name="natvis::x4hi">
<AlternativeType Name="natvis::x4lo" />
<DisplayString Condition="v==0">0</DisplayString>
<DisplayString Condition="v==1">1</DisplayString>
<DisplayString Condition="v==2">2</DisplayString>
<DisplayString Condition="v==3">3</DisplayString>
<DisplayString Condition="v==4">4</DisplayString>
<DisplayString Condition="v==5">5</DisplayString>
<DisplayString Condition="v==6">6</DisplayString>
<DisplayString Condition="v==7">7</DisplayString>
<DisplayString Condition="v==8">8</DisplayString>
<DisplayString Condition="v==9">9</DisplayString>
<DisplayString Condition="v==10">a</DisplayString>
<DisplayString Condition="v==11">b</DisplayString>
<DisplayString Condition="v==12">c</DisplayString>
<DisplayString Condition="v==13">d</DisplayString>
<DisplayString Condition="v==14">e</DisplayString>
<DisplayString>f</DisplayString>
</Type>
<Type Name="natvis::x8">
<DisplayString>{*(natvis::x4hi*)(this)}{*(natvis::x4lo*)(this)}</DisplayString>
</Type>
<Type Name="natvis::x32">
<DisplayString>{((natvis::x8*)this)[0]}{((natvis::x8*)this)[1]}{((natvis::x8*)this)[2]}{((natvis::x8*)this)[3]}</DisplayString>
</Type>
<Type Name="SHA1">
<DisplayString>{((natvis::x32*)hash)[0]}{((natvis::x32*)hash)[1]}{((natvis::x32*)hash)[2]} {((natvis::x32*)hash)[3]}{((natvis::x32*)hash)[4]}</DisplayString>
</Type>
Если вы можете получить доступ к массиву символов, определенному в коде, вы можете использовать формат строки ,1sb
и избегать любого разветвления. Добавьте [DLL export/extern/static] const char* hex_chars="0123456789abcdef";
в пространство имен natvis и замените 16 условных DisplayStrings на один:
<Type Name="natvis::x4hi">
<AlternativeType Name="natvis::x4lo" />
<DisplayString>{(hex_chars+v),1sb}</DisplayString>
</Type>
Насколько я знаю, нет способа использовать оператор контекста {,,mylib[d].dll}natvis::hex_chars
таким образом, который работает как с статическими, так и с DLL-сборками. Вы можете использовать static const char* hex_chars = "..."
, но это добавит строку в каждый .obj файл, который включает заголовок.
Пожалуйста, оставьте комментарий, если вы знаете решение, которое не вызывает раздувание:)
Ответ 2
Этот подход далеко не хорош, но он выполняет свою работу.
Во-первых, вам нужен фиктивный тип где-то в вашем коде, который обрабатывает отображение одного байта в шестнадцатеричном виде без каких-либо префиксов. Это похоже на действительно грязный взлом, поскольку мы должны ввести дополнительный код в наш код только для правильной визуализации отладки.
namespace dummy {
struct hex_dummy {
unsigned char c;
};
}
Этот тип может быть размещен практически везде, пока отладчик может найти его в контексте, где мы хотим посмотреть uuid.
Следующий шаг, к сожалению, почти так же плох. Чтобы иметь возможность печатать байты в шестнадцатеричном формате без префикса 0x
, мы вводим визуализатор отладки для hex_dummy
с колоссальным 256 различными DisplayStrings
:
<Type Name="dummy::hex_dummy">
<DisplayString Condition="(c == 0x00)">00</DisplayString>
<DisplayString Condition="(c == 0x01)">01</DisplayString>
<DisplayString Condition="(c == 0x02)">02</DisplayString>
<DisplayString Condition="(c == 0x03)">03</DisplayString>
<DisplayString Condition="(c == 0x04)">04</DisplayString>
<DisplayString Condition="(c == 0x05)">05</DisplayString>
<DisplayString Condition="(c == 0x06)">06</DisplayString>
<DisplayString Condition="(c == 0x07)">07</DisplayString>
<DisplayString Condition="(c == 0x08)">08</DisplayString>
<DisplayString Condition="(c == 0x09)">09</DisplayString>
<DisplayString Condition="(c == 0x0a)">0A</DisplayString>
<DisplayString Condition="(c == 0x0b)">0B</DisplayString>
<DisplayString Condition="(c == 0x0c)">0C</DisplayString>
<DisplayString Condition="(c == 0x0d)">0D</DisplayString>
<DisplayString Condition="(c == 0x0e)">0E</DisplayString>
<DisplayString Condition="(c == 0x0f)">0F</DisplayString>
<DisplayString Condition="(c == 0x10)">10</DisplayString>
<DisplayString Condition="(c == 0x11)">11</DisplayString>
...
Вы получаете идею.
С этим на месте визуализация uuid проста. Я использовал boost::uuid
для тестирования этого:
<Type Name="boost::uuids::uuid">
<DisplayString>uuid {*(dummy::hex_dummy*)(&data[0])}{*(dummy::hex_dummy*)(&data[1])}{*(dummy::hex_dummy*)(&data[2])}{*(dummy::hex_dummy*)(&data[3])}-{*(dummy::hex_dummy*)(&data[4])}{*(dummy::hex_dummy*)(&data[5])}-{*(dummy::hex_dummy*)(&data[6])}{*(dummy::hex_dummy*)(&data[7])}-{*(dummy::hex_dummy*)(&data[8])}{*(dummy::hex_dummy*)(&data[9])}-{*(dummy::hex_dummy*)(&data[10])}{*(dummy::hex_dummy*)(&data[11])}{*(dummy::hex_dummy*)(&data[12])}{*(dummy::hex_dummy*)(&data[13])}{*(dummy::hex_dummy*)(&data[14])}{*(dummy::hex_dummy*)(&data[15])}</DisplayString>
</Type>
Вы можете легко убедиться, что он работает, тестируя его с помощью uuid, созданного boost uuid_generator
:
boost::uuids::uuid const test_id =
boost::uuids::string_generator()("{01234567-89AB-CDEF-0123-456789ABCDEF}");
![enter image description here]()
Теперь это решение не только абиссально уродливое, но и кажется, что отладчик некоторое время работает через массивное ветвление hex_dummy
, что приводит к заметной задержке появления окна часового пояса при наведении курсора мыши на uuid while отладки.
Я не очень доволен этим решением, но пока это лучшее, что я мог бы придумать. Если кто-либо увидит какой-либо потенциал для улучшения, не жертвуя ясностью конечного результата, я был бы очень рад услышать их.
Изменить: Небольшое улучшение - путем введения двух фиктивных типов вместо одного я мог бы по крайней мере избавиться от задержки всплывающего окна. Идея состоит в двух использовании отдельных манекенов для печати верхнего и нижнего полубайта каждого байта, поэтому нам нужно сделать две 16-сторонние ветки на каждый байт вместо одной 256-way-ветки.
namespace dummy {
struct hex_dummy_low {
unsigned char c;
};
struct hex_dummy_high {
unsigned char c;
};
}
Прокси-визуализаторы:
<Type Name="dummy::hex_dummy_low">
<DisplayString Condition="((c & 0x0f) == 0x00)">0</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x01)">1</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x02)">2</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x03)">3</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x04)">4</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x05)">5</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x06)">6</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x07)">7</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x08)">8</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x09)">9</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0a)">A</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0b)">B</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0c)">C</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0d)">D</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0e)">E</DisplayString>
<DisplayString Condition="((c & 0x0f) == 0x0f)">F</DisplayString>
</Type>
<Type Name="dummy::hex_dummy_high">
<DisplayString Condition="((c >> 4) == 0x00)">0</DisplayString>
<DisplayString Condition="((c >> 4) == 0x01)">1</DisplayString>
<DisplayString Condition="((c >> 4) == 0x02)">2</DisplayString>
<DisplayString Condition="((c >> 4) == 0x03)">3</DisplayString>
<DisplayString Condition="((c >> 4) == 0x04)">4</DisplayString>
<DisplayString Condition="((c >> 4) == 0x05)">5</DisplayString>
<DisplayString Condition="((c >> 4) == 0x06)">6</DisplayString>
<DisplayString Condition="((c >> 4) == 0x07)">7</DisplayString>
<DisplayString Condition="((c >> 4) == 0x08)">8</DisplayString>
<DisplayString Condition="((c >> 4) == 0x09)">9</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0a)">A</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0b)">B</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0c)">C</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0d)">D</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0e)">E</DisplayString>
<DisplayString Condition="((c >> 4) == 0x0f)">F</DisplayString>
</Type>
И последний визуализатор uuid:
<Type Name="boost::uuids::uuid">
<DisplayString>uuid {*(dummy::hex_dummy_high*)(&data[0])}{*(dummy::hex_dummy_low*)(&data[0])}{*(dummy::hex_dummy_high*)(&data[1])}{*(dummy::hex_dummy_low*)(&data[1])}{*(dummy::hex_dummy_high*)(&data[2])}{*(dummy::hex_dummy_low*)(&data[2])}{*(dummy::hex_dummy_high*)(&data[3])}{*(dummy::hex_dummy_low*)(&data[3])}-{*(dummy::hex_dummy_high*)(&data[4])}{*(dummy::hex_dummy_low*)(&data[4])}{*(dummy::hex_dummy_high*)(&data[5])}{*(dummy::hex_dummy_low*)(&data[5])}-{*(dummy::hex_dummy_high*)(&data[6])}{*(dummy::hex_dummy_low*)(&data[6])}{*(dummy::hex_dummy_high*)(&data[7])}{*(dummy::hex_dummy_low*)(&data[7])}-{*(dummy::hex_dummy_high*)(&data[8])}{*(dummy::hex_dummy_low*)(&data[8])}{*(dummy::hex_dummy_high*)(&data[9])}{*(dummy::hex_dummy_low*)(&data[9])}-{*(dummy::hex_dummy_high*)(&data[10])}{*(dummy::hex_dummy_low*)(&data[10])}{*(dummy::hex_dummy_high*)(&data[11])}{*(dummy::hex_dummy_low*)(&data[11])}{*(dummy::hex_dummy_high*)(&data[12])}{*(dummy::hex_dummy_low*)(&data[12])}{*(dummy::hex_dummy_high*)(&data[13])}{*(dummy::hex_dummy_low*)(&data[13])}{*(dummy::hex_dummy_high*)(&data[14])}{*(dummy::hex_dummy_low*)(&data[14])}{*(dummy::hex_dummy_high*)(&data[15])}{*(dummy::hex_dummy_low*)(&data[15])}</DisplayString>
</Type>
Ответ 3
Вы можете попробовать мое расширение С++ Debugger Visualizer. Версия 1.0.16 поддерживает boost:: uuids:: uuid визуализатор, используя AddIn dll.
Ответ 4
Здесь простое решение, которое не требует дополнительных фиктивных структур в коде:
<Type Name="boost::uuids::uuid">
<DisplayString>{((((int32)data[3] & 0xFF)) + (((int32)data[2] & 0xFF) << 8) + (((int32)data[1] & 0xFF) << 16) + (((int32)data[0] & 0xFF) << 24)),X} - {((((int32)data[7] & 0xFF)) + (((int32)data[6] & 0xFF) << 8) + (((int32)data[5] & 0xFF) << 16) + (((int32)data[4] & 0xFF) << 24)),X} - {((((int32)data[11] & 0xFF)) + (((int32)data[10] & 0xFF) << 8) + (((int32)data[9] & 0xFF) << 16) + (((int32)data[8] & 0xFF) << 24)),X} - {((((int32)data[15] & 0xFF)) + (((int32)data[14] & 0xFF) << 8) + (((int32)data[13] & 0xFF) << 16) + (((int32)data[12] & 0xFF) << 24)),X}</DisplayString>
</Type>
Он не показывает UUID так же хорошо, как другие решения, он просто показывает его как 4 блока из 32-битных целых чисел, но он выполняет задание:
![uuid visualizer]()