VS2012 で NatVis 経由で UUID を表示する適切な方法を探しています。私自身の uuid タイプは内部で UUID ビッグ エンディアンを使用するため、Windows では GUID がリトルエンディアンを使用するため、(GUID*) へのキャストは機能しません。そのため、誤って伝えられた uuid が常に表示されます。
さらに、16 進表記を使用すると出力の 0x を取り除くことができないため、Natvis の形式指定子は見栄えがよくありません。何か案は?
VS2012 で NatVis 経由で UUID を表示する適切な方法を探しています。私自身の uuid タイプは内部で UUID ビッグ エンディアンを使用するため、Windows では GUID がリトルエンディアンを使用するため、(GUID*) へのキャストは機能しません。そのため、誤って伝えられた uuid が常に表示されます。
さらに、16 進表記を使用すると出力の 0x を取り除くことができないため、Natvis の形式指定子は見栄えがよくありません。何か案は?
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 _; };
}
ナットビス
<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 個の条件付き DisplayString を 1 つに置き換えます。
<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 ファイルに文字列が追加されます。
肥大化を引き起こさない解決策を知っている場合は、コメントを残してください:)
このアプローチはきれいとは言えませんが、仕事は完了します。
まず、プレフィックスなしで 16 進数の 1 バイトの表示を処理する、コードのどこかにダミーの型が必要です。適切なデバッグの視覚化のためだけに追加の型をコードに導入する必要があるため、これは非常に汚いハックのように感じます。
namespace dummy {
struct hex_dummy {
unsigned char c;
};
}
このタイプは、デバッガーが uuid を確認したいコンテキストで見つけることができる限り、ほとんどどこにでも配置できます。
残念ながら、次のステップはほとんど同じくらい悪いです。0x
プレフィックスなしでバイトを 16 進数で出力できるようにするため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>
boost によって作成された uuid を使用してテストすることで、動作することを簡単に確認できますuuid_generator
。
boost::uuids::uuid const test_id =
boost::uuids::string_generator()("{01234567-89AB-CDEF-0123-456789ABCDEF}");
現在、このソリューションはひどく醜いだけでなく、デバッガーが大規模なhex_dummy
分岐を処理するのに時間がかかるようであり、デバッグ中にuuidにカーソルを合わせると、マウスオーバーウォッチウィンドウがポップアップするのに顕著な遅延が生じます.
私はこの解決策に満足しているわけではありませんが、これまでのところ、私が思いつくことができる最高のものです. 最終的な出力の明瞭さを犠牲にすることなく改善の可能性を誰かが見つけたら、私は本当に喜んで聞いてくれるでしょう.
編集:マイナーな改善 - 1 つではなく 2 つのダミー タイプを導入することで、少なくともポップアップの遅延を取り除くことができました。アイデアは、各バイトの上位ニブルと下位ニブルを出力するために 2 つの別々のダミーを使用することです。そのため、1 つの 256 方向の分岐ではなく、バイトごとに 2 つの 16 方向の分岐を行う必要があります。
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>
コードに追加のダミー構造体を必要としない単純なソリューションを次に示します。
<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 は他のソリューションほどうまく表示されず、単に 32 ビット整数の 4 つのブロックとして表示されますが、機能します。
私の拡張C++ Debugger Visualizersを試すことができます。バージョン 1.0.16 は、 AddIn dllを使用して boost::uuids::uuid ビジュアライザーをサポートします。