<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Apr 29, 2014, at 6:50 AM, Eran Ifrah <<a href="mailto:eran.ifrah@gmail.com">eran.ifrah@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">Hi Enrico and all,</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">Thanks for the references, it helped me a lot.</div>


<div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">I am now able to view QString within lldb from the <b>command line</b>, but not from within my plugin :P (this was my intention all the way)</div>

<div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">I created the following 2 files:</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">

~/.lldbinit, with this single line:</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small"><br></div><div class="gmail_default" style=""><font face="courier new, monospace">command script import /home/eran/.lldb/qstring.py</font><br>

</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small"><br></div>
<div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">In the script: ~/.lldb/qstring.py, I placed the following content (a slightly modified printer based on your example):</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">

<br></div><div class="gmail_default" style=""><div class="gmail_default" style=""><font face="courier new, monospace">import lldb</font></div><div class="gmail_default" style=""><font face="courier new, monospace"><br></font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">def utf16string_summary(value, *rest):</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    f = open('/tmp/py.log','w+b')</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    f.write('inside utf16string_summary\n')</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    f.close()</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    str_data = value.GetChildMemberWithName("d").GetChildMemberWithName("data")</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    length_vo = value.GetChildMemberWithName("d").GetChildMemberWithName("size")</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    length = length_vo.GetValueAsUnsigned(0)</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    if length == 0:</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">        return '""'</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    data = str_data.GetPointeeData(0, length)</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    error = lldb.SBError()</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    bytes = data.ReadRawData(error, 0, 2*length)</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    return '"%s"' % (bytes.decode('utf-16').encode('utf-8'))</font></div><div class="gmail_default" style=""><font face="courier new, monospace"><br>

</font></div><div class="gmail_default" style=""><font face="courier new, monospace">def __lldb_init_module(debugger, *rest):</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    summary = lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary")</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">    summary.SetOptions(lldb.eTypeOptionHideChildren)</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    debugger.GetDefaultCategory().AddTypeSummary( lldb.SBTypeNameSpecifier("QString", False), summary )</font></div>

<div class="gmail_default" style=""><font face="verdana, sans-serif"><br></font></div><div class="gmail_default" style=""><font face="verdana, sans-serif">This setup works when I am using lldb-3.5 from the command line (i.e. QString is displayed in the following format: m_stringMemeber = "some content")</font></div>

<div class="gmail_default" style=""><font face="verdana, sans-serif"><br></font></div></div></div></blockquote><div><br></div><div>How recent/non recent is lldb-3.5?</div><div>Did you try with trunk at all?</div><br><blockquote type="cite"><div dir="ltr"><div class="gmail_default" style=""><div class="gmail_default" style=""><font face="verdana, sans-serif">Now, this is how I set it up from within my plugin:</font></div><div class="gmail_default" style="">

<font face="verdana, sans-serif"><br></font></div><div class="gmail_default" style=""><font face="verdana, sans-serif">I tried both:</font></div><div class="gmail_default" style=""><span style="font-family:'courier new',monospace">m_debugger = lldb::SBDebugger::Create(true); // source init files</span><br>

</div><div class="gmail_default" style=""><font face="verdana, sans-serif"><br></font></div><div class="gmail_default" style=""><font face="verdana, sans-serif">and I have also tried this:</font></div><div class="gmail_default" style="">

<font face="verdana, sans-serif"><br></font></div><div class="gmail_default" style=""><font face="courier new, monospace">m_debugger = lldb::SBDebugger::Create();<br></font></div><div class="gmail_default" style=""><font face="courier new, monospace">...</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">lldb::SBCommandReturnObject ret;<br></font></div><div class="gmail_default" style=""><font face="courier new, monospace">m_debugger.GetCommandInterpreter().HandleCommand("command source /home/eran/.lldbinit", ret);<br>

</font></div><div class="gmail_default" style=""><font face="courier new, monospace">if ( !ret.Succeeded() ) {</font></div><div class="gmail_default" style=""><font face="courier new, monospace">    // print error here if any</font></div>

<div class="gmail_default" style=""><font face="courier new, monospace">}</font></div><div class="gmail_default" style=""><font face="verdana, sans-serif"><br></font></div><div class="gmail_default" style=""><font face="verdana, sans-serif">Both did not have any affect, i.e. when I view the content of QString in the IDE, I don't see the summary as it should</font></div>

<div class="gmail_default" style=""><font face="verdana, sans-serif">Any hints?</font></div><div class="gmail_default" style=""><font face="verdana, sans-serif"><br></font></div></div></div></blockquote><div><br></div><div>Well, I see two - or rather three - potential issues</div><div>First of all, Is the summary loaded? To check if it is, run “type summary list” and make sure you see a formatter for QString listed in the default category - and that the default category is enabled</div><div>Second, is the summary working? If it is loaded, we can test it manually: do something like this while you’re stopped in a frame with a QString variable</div><div>(lldb) script value = lldb.frame.FindVariable(“myQStringThingNameHere”)</div><div>(lldb) script print qstring.utf16string_summary(value,None)</div><div><br></div><div>Does anything come out with a manual invocation?</div><div><br></div><div>Assuming the summary is registered, and manually calling it works - how are you fetching the summary in your plugin?</div><div>Since it works at the command line, I assume the type name for QString is just plain QString with no namespaces in front. Is that correct?</div><br><blockquote type="cite"><div dir="ltr"><div class="gmail_default" style=""><div class="gmail_default" style=""><font face="verdana, sans-serif">Thanks</font></div>

</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Apr 29, 2014 at 3:38 AM, Enrico Granata <span dir="ltr"><<a href="mailto:egranata@apple.com" target="_blank">egranata@apple.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div class="h5">On Apr 28, 2014, at 3:01 PM, Poenitz Andre <<a href="mailto:Andre.Poenitz@digia.com" target="_blank">Andre.Poenitz@digia.com</a>> wrote:<br>

<div><br><blockquote type="cite"><div style="font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;direction:ltr;font-family:Tahoma;font-size:10pt">

<br>Enrico Granata wrote:<br>> Eran Ifrah wrote:<br><div style="font-family:'Times New Roman';font-size:16px">> You can't use expressions in summary strings.<div><div>> We have thought about this several times and have a couple ideas on how<span> </span><br>

> it could be done but for now it's not there.</div><div>><br></div><div>> If you need to resort to an expression, you can use a python formatter<br>> instead and then you are free to call as many expressions as you like.</div>

<div>><br></div><div>> However, this will cause a slowdown - running expressions is not<br>> free - and if you ever need to make sure nothing is altering your<br>> program state, running expressions might not be a safe bet.</div>

<div>> Is there really no other way to get to those UTF8 bytes?<br><br>QString is stored in UTF16 internally. It can be accessed directly<span> </span><br>through structure member access and pointer arithmetic and converted<span> </span><br>

using Python. "Running expressions" is not needed.<br><br>Andre'</div></div></div></div></blockquote></div><div><br></div></div></div><div>Here’s a small example for general reference:</div><div>Assume I have the following data structure:</div>

<div><br></div><div><font face="Menlo"><span style="font-size:11px">#include <string><br>#include <memory><br><br>class UTF16String {<br>public:<br>  UTF16String (const char16_t *data) {<br>    len = std::char_traits<char16_t>::length(data);<br>

    str_data.reset(new char16_t[len]);<br>    memcpy(str_data.get(),data,sizeof(char16_t)*(len+1));<br>  }<br>  <br>private:<br>  std::unique_ptr<char16_t[]> str_data;<br>  size_t len;<br>};<br><br>int main() {<br>
  UTF16String string {u"Just some data in UTF16 here"};<br>
  return 0;<br>}<br></span></font><br><br></div><div>This is what it looks like “raw” on OS X:</div><div><font face="Menlo"><span style="font-size:11px">(UTF16String) string = {<br>  str_data = {<br>    __ptr_ = {<br>

      std::__1::__libcpp_compressed_pair_imp<char16_t *, std::__1::default_delete<char16_t> > = {<br>        __first_ = 0x00000001001037e0<br>      }<br>    }<br>  }<br>  len = 28<br>}<br></span></font><br></div>

<div>To define a formatter for it you essentially want to grab two elements: the data pointer (__first_ = 0x00000001001037e0) and the length (len = 30)</div><div>In our example, the length is defined in UTF16-characters rather than bytes. This is something you want to know when writing a formatter</div>

<div><br></div><div>So let’s delve right in:</div><div><div><font face="Menlo"><span style="font-size:11px">def utf16string_summary(value,*rest):</span></font></div><div><font face="Menlo"><span style="font-size:11px">  str_data = value.GetChildMemberWithName("str_data").GetChildMemberWithName("__ptr_").GetChildMemberWithName("__first_")</span></font></div>

<div><font face="Menlo"><span style="font-size:11px">  length_vo = value.GetChildMemberWithName("len")</span></font></div></div><div><br></div><div>Now we have SBValues for the string data and for the length - we want the “number stored inside” the length:</div>

<div><div><font face="Menlo"><span style="font-size:11px">  length = length_vo.GetValueAsUnsigned(0)</span></font></div><div><font face="Menlo"><span style="font-size:11px">  if length == 0:</span></font></div><div><font face="Menlo"><span style="font-size:11px">    return '""'</span></font></div>

</div><div><br></div><div>As a special case - if the length is zero, just return an empty string. I am not going to go in detail over all the possible checks here (hint: what if str_data’s value is zero?)</div><div><br></div>

<div>Now let’s grab the bytes - we want length char16_t at the location pointed to by our str_data:</div><div><div><font face="Menlo"><span style="font-size:11px">  data = str_data.GetPointeeData(0,length)</span></font></div>

</div><div><br></div><div>And now let’s grab a Python string out of those bytes:</div><div><div><font face="Menlo"><span style="font-size:11px">  error = lldb.SBError()</span></font></div><div><font face="Menlo"><span style="font-size:11px">  bytes = data.ReadRawData(error,0,2*length)<br>

</span></font><br></div></div><div>The 2*length argument is <i>carefully</i> crafted to ensure we get all the bytes we need - it of course depends on sizeof(char16_t) == 2</div><div><br></div><div>Python is pretty good at string management, all we have to do now is tell it to turn our string from UTF16 into UTF8:</div>

<div><font face="Menlo"><span style="font-size:11px">  return '"%s"' % (bytes.decode('utf-16').encode('utf-8'))</span></font></div><div><br></div><div>You’re done. To add the summary automatically to LLDB whenever you command script import the python file with the formatter:</div>

<div><div><font face="Menlo"><span style="font-size:11px">def __lldb_init_module(debugger,*rest):</span></font></div><div><font face="Menlo"><span style="font-size:11px">  summary = lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary")</span></font></div>

<div><font face="Menlo"><span style="font-size:11px">  summary.SetOptions(lldb.eTypeOptionHideChildren)</span></font></div><div><font face="Menlo"><span style="font-size:11px">  debugger.GetDefaultCategory().AddTypeSummary(lldb.SBTypeNameSpecifier("UTF16String",False),summary)</span></font></div>

<div><br></div></div><div>This is what you get with the summary enabled:</div><div>(UTF16String) string = "Just some data in UTF16 here”<br><br></div><div>Find the C++ and the Python parts of the example attached for reference - and of course feel free to ping back with any additional questions</div>

<div><br></div></div><br><div style="word-wrap:break-word"></div>
<br><div style="word-wrap:break-word"><br><div>
<div style="text-indent:0px;letter-spacing:normal;text-align:start;text-transform:none;white-space:normal;word-wrap:break-word;word-spacing:0px"><div style="text-indent:0px;letter-spacing:normal;text-align:start;text-transform:none;white-space:normal;word-wrap:break-word;word-spacing:0px">

<div style="text-indent:0px;letter-spacing:normal;text-align:start;text-transform:none;white-space:normal;word-wrap:break-word;word-spacing:0px"><div style="text-indent:0px;letter-spacing:normal;text-align:start;text-transform:none;white-space:normal;word-wrap:break-word;word-spacing:0px">

<div><i>- Enrico</i><br>📩 egranata@<font color="#ff2600"></font>.com ☎️ 27683</div><div><br></div></div></div></div></div><br>
</div>
<br></div><br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr">Eran Ifrah<br>Author of codelite, a cross platform open source C/C++ IDE: <a href="http://www.codelite.org/" target="_blank">http://www.codelite.org</a><br>

<div>wxCrafter, a wxWidgets RAD: http://<a href="http://wxcrafter.codelite.org/" target="_blank">wxcrafter.codelite.org</a></div></div>
</div>
</blockquote></div><br><div>
<div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div><i>- Enrico</i><br>📩 egranata@<font color="#ff2600"></font>.com ☎️ 27683</div><div><br></div></div></div></div></div><br class="Apple-interchange-newline">
</div>
<br></body></html>