<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Well that seems to imply we don't know what the qstring module is when trying to use it to run the formatter</div><div><br></div><div>How are you loading the python script from your plugin?</div><div><br></div><div>Another thing that you could try is debug LLDB and see what happens when we try fetching the summary. I am expecting we will fail to find the function object and then we can take it from there.<br><br>Sent from the iPhone of<div><i>Enrico Granata</i> <egranata@🍎.com></div></div><div><br>On Apr 29, 2014, at 1:20 PM, Eran Ifrah <<a href="mailto:eran.ifrah@gmail.com">eran.ifrah@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small"><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Apr 29, 2014 at 8:15 PM, 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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div class="h5"><div>On Apr 29, 2014, at 6:50 AM, Eran Ifrah <<a href="mailto:eran.ifrah@gmail.com" target="_blank">eran.ifrah@gmail.com</a>> wrote:</div>
<br><blockquote type="cite"><div dir="ltr"><div style="font-family:verdana,sans-serif;font-size:small">Hi Enrico and all,</div><div style="font-family:verdana,sans-serif;font-size:small">Thanks for the references, it helped me a lot.</div>
<div 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 style="font-family:verdana,sans-serif;font-size:small"><br></div><div style="font-family:verdana,sans-serif;font-size:small">I created the following 2 files:</div><div style="font-family:verdana,sans-serif;font-size:small">
~/.lldbinit, with this single line:</div><div style="font-family:verdana,sans-serif;font-size:small"><br></div><div><font face="courier new, monospace">command script import /home/eran/.lldb/qstring.py</font><br>
</div><div style="font-family:verdana,sans-serif;font-size:small"><br></div>
<div 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 style="font-family:verdana,sans-serif;font-size:small">
<br></div><div><div><font face="courier new, monospace">import lldb</font></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">def utf16string_summary(value, *rest):</font></div><div><font face="courier new, monospace"> f = open('/tmp/py.log','w+b')</font></div>
<div><font face="courier new, monospace"> f.write('inside utf16string_summary\n')</font></div><div><font face="courier new, monospace"> f.close()</font></div>
<div><font face="courier new, monospace"> str_data = value.GetChildMemberWithName("d").GetChildMemberWithName("data")</font></div><div><font face="courier new, monospace"> length_vo = value.GetChildMemberWithName("d").GetChildMemberWithName("size")</font></div>
<div><font face="courier new, monospace"> length = length_vo.GetValueAsUnsigned(0)</font></div><div><font face="courier new, monospace"> if length == 0:</font></div>
<div><font face="courier new, monospace"> return '""'</font></div><div><font face="courier new, monospace"> data = str_data.GetPointeeData(0, length)</font></div>
<div><font face="courier new, monospace"> error = lldb.SBError()</font></div><div><font face="courier new, monospace"> bytes = data.ReadRawData(error, 0, 2*length)</font></div>
<div><font face="courier new, monospace"> return '"%s"' % (bytes.decode('utf-16').encode('utf-8'))</font></div><div><font face="courier new, monospace"><br>
</font></div><div><font face="courier new, monospace">def __lldb_init_module(debugger, *rest):</font></div><div><font face="courier new, monospace"> summary = lldb.SBTypeSummary.CreateWithFunctionName("qstring.utf16string_summary")</font></div>
<div><font face="courier new, monospace"> summary.SetOptions(lldb.eTypeOptionHideChildren)</font></div><div><font face="courier new, monospace"> debugger.GetDefaultCategory().AddTypeSummary( lldb.SBTypeNameSpecifier("QString", False), summary )</font></div>
<div><font face="verdana, sans-serif"><br></font></div><div><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><font face="verdana, sans-serif"><br></font></div></div></div></blockquote><div><br></div></div></div><div>How recent/non recent is lldb-3.5?</div><div>Did you try with trunk at all?</div></div></div></blockquote><div>
<br><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">On this VirtualBox, I am using the Ubuntu 14.04 packages (the package name is lldb-3.5-dev, but I am not sure of which revision is it...)<br>
</div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div class=""><br><blockquote type="cite"><div dir="ltr">
<div><div><font face="verdana, sans-serif">Now, this is how I set it up from within my plugin:</font></div><div>
<font face="verdana, sans-serif"><br></font></div><div><font face="verdana, sans-serif">I tried both:</font></div><div><span style="font-family:'courier new',monospace">m_debugger = lldb::SBDebugger::Create(true); // source init files</span><br>
</div><div><font face="verdana, sans-serif"><br></font></div><div><font face="verdana, sans-serif">and I have also tried this:</font></div><div>
<font face="verdana, sans-serif"><br></font></div><div><font face="courier new, monospace">m_debugger = lldb::SBDebugger::Create();<br></font></div><div><font face="courier new, monospace">...</font></div>
<div><font face="courier new, monospace">lldb::SBCommandReturnObject ret;<br></font></div><div><font face="courier new, monospace">m_debugger.GetCommandInterpreter().HandleCommand("command source /home/eran/.lldbinit", ret);<br>
</font></div><div><font face="courier new, monospace">if ( !ret.Succeeded() ) {</font></div><div><font face="courier new, monospace"> // print error here if any</font></div>
<div><font face="courier new, monospace">}</font></div><div><font face="verdana, sans-serif"><br></font></div><div><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><font face="verdana, sans-serif">Any hints?</font></div><div><font face="verdana, sans-serif"><br></font></div></div></div></blockquote><div><br></div></div><div>Well, I see two - or rather three - potential issues</div>
<div>First of all, Is the summary loaded?</div></div></div></blockquote><div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">Yes, it does. <br></div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">
After the debug session I added a call for debug purposes:<br>m_debugger.GetCommandInterpreter().HandleCommand("type summary list", ret);<br></div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">
And here are the relevant parts:<br></div> <br><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">[ 22:55:49:193 DBG ] codelite-lldb: type summary list returned:<br>[ 22:55:49:193 DBG ] -----------------------<br>
[ 22:55:49:193 DBG ] Category: default (enabled)<br>[ 22:55:49:193 DBG ] -----------------------<br>[ 22:55:49:193 DBG ] QString: (not cascading)<br>[ 22:55:49:193 DBG ] wxPoint: `x = ${var.x}, y = ${var.y}`<br>[ 22:55:49:193 DBG ] wxRect: `(x = ${var.x}, y = ${var.y}) (width = ${var.width}, height = ${var.height})`<br>
[ 22:55:49:193 DBG ] wxString: `${var.m_impl._M_dataplus._M_p}`<br>[ 22:55:49:193 DBG ] -----------------------<br>[ 22:55:49:193 DBG ] Category: objc (enabled)<br>[ 22:55:49:193 DBG ] -----------------------<br><br></div>
<div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">The first one "QString" was added using python script, the following 3 (wxPoint, wxString and wxRect) were added using 'type summary add..' simple command all 3 are working (from within my plugin). The fact that the wx* summaries are working properly within the plugin give me confident that the method I am using to retrieve the data is correct.<br>
<br><br><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div> 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) <div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">
</div>script value = lldb.frame.FindVariable(“myQStringThingNameHere”)</div><div>(lldb) <div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline"></div>script print qstring.utf16string_summary(value,None)</div>
<div><br></div></div></div></blockquote><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">Arg, I don't have a 'console' where I can free type commands ( I will definitely add one to the plugin)<br>
</div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">For now, I added the above commands manually for debug purposes and here are the results:<br><br>[ 23:13:24:029 DBG ] codelite-lldb: output of command 'script print qstring.utf16string_summary(value, None)':<br>
[ 23:13:24:029 DBG ] Traceback (most recent call last):<br>[ 23:13:24:029 DBG ] File "<input>", line 1, in <module><br>[ 23:13:24:029 DBG ] NameError: name 'qstring' is not defined<br><br>
</div>
<div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small">The log clearly shows that it does not know what 'qstring' is... but what?<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div style="word-wrap:break-word"><div><div></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></div></blockquote><div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">I don't think that this is the case as it works for other summaries (e.g. wxString)<br></div>
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><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>
</div></div></blockquote><div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">Yes, the same code (with the same ~/.lldbinit) running from command line:<br><br>(lldb) <br>
Process 21809 stopped<br>
* thread #1: tid = 21809, 0x0000000000400ae5 TestQString`main(argc=1, argv=0x00007fff922a8688) + 184 at main.cpp:11, name = 'TestQString', stop reason = step over<br> frame #0: 0x0000000000400ae5 TestQString`main(argc=1, argv=0x00007fff922a8688) + 184 at main.cpp:11<br>
8 Q_UNUSED( argv );<br> 9 QString str;<br> 10 str = QString("Hello %1").arg("world");<br>-> 11 printf("%s\n", str.toLocal8Bit().constData());<br> 12 return 0;<br>
13 }<br>(lldb) p str<br>(QString) $0 = "Hello world"<br><br></div><div class="gmail_default" style="font-family:verdana,sans-serif;font-size:small;display:inline">Note that the 'lldb' from the command line is was also installed from the Ubuntu package lldb-3.5-dev, so we can also rule that one out...<br>
<br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div><div class="h5"><br><blockquote type="cite">
<div dir="ltr"><div><div><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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>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></div></div><div><div class="h5"><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></div></div></blockquote></div><br><br clear="all"><br>-- <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></div>
</div></blockquote></body></html>