[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    Re: [PyQt] DOUBTT
From:       Chris Kaynor <ckaynor () zindagigames ! com>
Date:       2014-07-23 22:36:58
Message-ID: CALvWhxuQvPtVvTM3CUmeFyNLw5xwzu5D=js2km5Hzu69aqs9LA () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Wed, Jul 23, 2014 at 2:59 PM, Amey Patil <amey.patil@sjsu.edu> wrote:

> Hi,
> I am at the basic level in using sip wrapper in python. I have written a
> small library in c++ and wrapping it in sip for execution in Python.
> Copy pasting my entire files for better understanding. Also pasting the
> output from the terminal, the behaviour i am getting is completely
> unexpected, can you please look into it...
>

I've included some options. As I do not know your overall skill level in
C++/Python, I have included quite a bit of detail overall.

Without knowing your full use cases, in addition to sip, you may want to
look at Cython (compiles a very Python-like language to C code), using the
Python C APIs directly (a fairly direct replacement for sip), or using PyPy
(which has a JIT compiler for Python to speed it up). Each of the four
options has its own benefits and drawbacks.


>
> *word.h:*
>
> class Word
> {
>
> public:
>     int integer;
>     const char *name;
>     Word();
>     void set_name(const char *a);
>     void reset_name();
>     const char *get_name();
> };
>
> *word.cpp:*
>
> #include <iostream>
> #include "word.h"
>
> using namespace std;
>
> Word::Word(){
>     name = "PyQt";
>
> }
>
> void Word::set_name(const char *a){
>     cout << "parameter passed to set_name is " << a << endl;
>     cout << "name before set_name is " << name << endl;
>     name = a;
>

This line is probably your problem. You'll probably want to copy the string
"a" into a buffer rather than assign the pointer. Without this, as soon as
the string pointed to by "a" is deallocated, the name parameter becomes
invalid. This is known as a dangling pointer, and can cause odd bugs, such
as getting random values or crashing when accessing.

For cases where a will be a constant, hard-coded, C variable (such as for
reset_name below), the string will typically be held in a data section that
will live for as long as the program runs, and thus it will work. If you
were to call set_name from a value read from a file, however, you'd likely
find the name will change later, similar to the sip-wrapped code.

There are a few common ways to deal with this in C:
1) Use a constant size char buffer, such as, in the class use "char
name[32]" rather than "const char *name", then use strcpy to copy the new
value into the fixed-size buffer. Be aware of the issues with copying more
than the size of the buffer!
2) Use a dynamically allocated array: use the malloc function or new
operator to make the name buffer based on the length of the string set,
then do the strcpy as above. You have to be sure to properly free the
memory when destroying the Word object or when new memory is allocated for
name. You can also use a string class such as std::string (C++ standard
library) which does this internally, with safety mechanisms.
3) Keep a reference to the Python string object. I do not know how to make
sip do this (I haven't really used sip much). This will keep the memory
valid, however you also have to be sure that when the reference is released
when the name is changed again or the Word object is destroyed.


>     cout << "name after set_name is " << name << endl;
> }
>

>
void Word::reset_name(){
>     cout << "name before reset_name is " << name << endl;
>     const char *x = "Epics";
>     name = x;
>
    cout << "name after reset_name is " << name << endl;
> }
>
> const char *Word::get_name(){
>     cout << "name before get_name is " << name << endl;
>     return name;
> }
>
> *word.sip:*
>
> %Module word
>
> class Word
> {
>
> %TypeHeaderCode
> #include <word.h>
> %End
>
> public:
>     int integer;
>     const char *name;
>     Word();
>     void set_name(const char *a);
>     void reset_name();
>     const char *get_name();
> };
>
> *Output in Python (Terminal):*
>
> >>> import word
> >>> w = word.Word()
>  >>> w.get_name()
> name before get_name is PyQt
> 'PyQt'
> >>> w.set_name("Amey")
> parameter passed to set_name is Amey
> name before set_name is PyQt
> name after set_name is Amey
>

After the set_name call returns, the Python object "Amey" goes out of
scope, and Python may garbage collect it. Often, this happens immediately,
however for various reasons it could be kept around for a while. Try
assigning "Amey" to a variable, then pass that variable into the function;
the following code will probably work, until you replace or delete the
variable, or the variable goes out of scope. Such an assignment will be
similar to keeping a reference around in the C code (as mentioned above, I
do not know how to do so with sip).


> >>> w.get_name()
> name before get_name is
> ''
>

You've just read the memory that used to point to the string "Amey", but
has been reused for other reasons. The new reason may change each time, and
eventually the memory may be completely freed at the OS level, or used for
a purpose for which you cannot read the memory, at which point you will get
a crash.


> >>> w.reset_name()
> name before reset_name is <stdin>
> name after reset_name is Epics
> >>> w.get_name()
> name before get_name is Epics
> 'Epics'
>
> PROBLEMS:
> 1. It won't print the output when i call get_name() after calling
> set_name().
> 2. As you can see in the output, I am editing nothing between the
> highlighted lines, still the output shows nothing in one while <stdin> in
> other.
>
> Please tell me what's wrong.
>
> Looking forward for your reply,
>
> Sincere Regards,
> Amey Patil
>
> _______________________________________________
> PyQt mailing list    PyQt@riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
>

[Attachment #5 (text/html)]

<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jul 23, 2014 \
at 2:59 PM, Amey Patil <span dir="ltr">&lt;<a href="mailto:amey.patil@sjsu.edu" \
target="_blank">amey.patil@sjsu.edu</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div>Hi,<br>I am at the basic level in using sip wrapper in python. I have \
written a small library in c++ and wrapping it in sip for execution in Python.<br>

Copy pasting my entire files for better understanding. Also pasting
 the output from the terminal, the behaviour i am getting is completely unexpected, \
can you  please look into \
it...<br></div></div></blockquote><div><br></div><div>I&#39;ve included some options. \
As I do not know your overall skill level in C++/Python, I have included quite a bit \
of detail overall.</div><div><br>

</div><div>Without knowing your full use cases, in addition to sip, you may want to \
look at Cython (compiles a very Python-like language to C code), using the Python C \
APIs directly (a fairly direct replacement for sip), or using PyPy (which has a JIT \
compiler for Python to speed it up). Each of the four options has its own benefits \
and drawbacks.</div>

<div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div><br> </div><div><b>word.h:</b><br><span \
style="color:rgb(255,0,0)"><br><span style="color:rgb(102,102,102)">class \
Word<br>{<br><br>public:<br>       int integer;<br>       const char *name;<br>       \
Word();<br>       void set_name(const char *a);<br>



       void reset_name();<br>       const char *get_name();<br>};</span></span><span \
style="color:rgb(102,102,102)"><br></span><br></div><div><b>word.cpp:</b><br><span \
style="color:rgb(102,102,102)"><br>#include &lt;iostream&gt;<br>



#include &quot;word.h&quot;<br><br>using namespace std;<br><br>Word::Word(){<br>      \
name = &quot;PyQt&quot;;<div><br>}<br><br>void Word::set_name(const char \
*a){<br></div>       cout &lt;&lt; &quot;parameter passed to set_name is &quot; \
&lt;&lt; a &lt;&lt; endl;<br>



       cout &lt;&lt; &quot;name before set_name is &quot; &lt;&lt; name &lt;&lt; \
endl;<br>       name = a;<br></span></div></div></blockquote><div><br></div><div>This \
line is probably your problem. You&#39;ll probably want to copy the string \
&quot;a&quot; into a buffer rather than assign the pointer. Without this, as soon as \
the string pointed to by &quot;a&quot; is deallocated, the name parameter becomes \
invalid. This is known as a dangling pointer, and can cause odd bugs, such as getting \
random values or crashing when accessing.</div>

<div><br></div><div>For cases where a will be a constant, hard-coded, C variable \
(such as for reset_name below), the string will typically be held in a data section \
that will live for as long as the program runs, and thus it will work. If you were to \
call set_name from a value read from a file, however, you&#39;d likely find the name \
will change later, similar to the sip-wrapped code.</div>

<div><br></div><div>There are a few common ways to deal with this in C:</div><div>1) \
Use a constant size char buffer, such as, in the class use &quot;char name[32]&quot; \
rather than &quot;const char *name&quot;, then use strcpy to copy the new value into \
the fixed-size buffer. Be aware of the issues with copying more than the size of the \
buffer!</div>

<div>2) Use a dynamically allocated array: use the malloc function or new operator to \
make the name buffer based on the length of the string set, then do the strcpy as \
above. You have to be sure to properly free the memory when destroying the Word \
object or when new memory is allocated for name. You can also use a string class such \
as std::string (C++ standard library) which does this internally, with safety \
mechanisms.</div>

<div>3) Keep a reference to the Python string object. I do not know how to make sip \
do this (I haven&#39;t really used sip much). This will keep the memory valid, \
however you also have to be sure that when the reference is released when the name is \
changed again or the Word object is destroyed.</div>

<div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div><span style="color:rgb(102,102,102)">       cout &lt;&lt; &quot;name \
after set_name is &quot; &lt;&lt; name &lt;&lt; endl;<br>

}</span>  </div></div></blockquote><blockquote class="gmail_quote" style="margin:0px \
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div>  </div>

</div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div><span style="color:rgb(102,102,102)">void Word::reset_name(){<br>



       cout &lt;&lt; &quot;name before reset_name is &quot; &lt;&lt; name &lt;&lt; \
endl;<br>       const char *x = &quot;Epics&quot;;<br>       name = \
x;</span></div></div></blockquote><blockquote class="gmail_quote" style="margin:0px \
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


<div dir="ltr"><div><span style="color:rgb(102,102,102)">       cout &lt;&lt; \
&quot;name after reset_name is &quot; &lt;&lt; name &lt;&lt; endl;<br>

}<br><br>const char *Word::get_name(){<br>       cout &lt;&lt; &quot;name before \
get_name is &quot; &lt;&lt; name &lt;&lt; endl;<br>       return \
name;<br>}</span><br><br></div><div><b>word.sip:</b><br><span \
style="color:rgb(102,102,102)"><br>



%Module word <br><br>class Word<br>{<br><br>%TypeHeaderCode<br>#include \
&lt;word.h&gt;<br>%End<br><br>public:<br>       int integer;<br>       const char \
*name;<br>       Word();<br>       void set_name(const char *a);<br>       void \
reset_name();<br>



       const char *get_name();<br>};</span><br><br></div><div><b>Output in Python \
(Terminal):</b><br><span style="color:rgb(255,0,0)"><br><span \
style="color:rgb(102,102,102)"><div>&gt;&gt;&gt; import word<br>&gt;&gt;&gt; w = \
word.Word()<br>


</div>
&gt;&gt;&gt; w.get_name()<br>name before get_name is \
PyQt<br>&#39;PyQt&#39;<br>&gt;&gt;&gt; w.set_name(&quot;Amey&quot;)<br>parameter \
passed to set_name is Amey<br>name before set_name is PyQt<br>name after set_name is \
Amey<br>

</span></span></div></div></blockquote><div><br></div><div>After the set_name call \
returns, the Python object &quot;Amey&quot; goes out of scope, and Python may garbage \
collect it. Often, this happens immediately, however for various reasons it could be \
kept around for a while. Try assigning &quot;Amey&quot; to a variable, then pass that \
variable into the function; the following code will probably work, until you replace \
or delete the variable, or the variable goes out of scope. Such an assignment will be \
similar to keeping a reference around in the C code (as mentioned above, I do not \
know how to do so with sip).</div>

<div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div><span style="color:rgb(255,0,0)"><span style="color:rgb(102,102,102)">

&gt;&gt;&gt; w.get_name()<br><span style="background-color:rgb(255,255,0)">name \
before get_name is </span><br>&#39;&#39;<br></span></span></div></div></blockquote><div><br></div><div>You&#39;ve \
just read the memory that used to point to the string &quot;Amey&quot;, but has been \
reused for other reasons. The new reason may change each time, and eventually the \
memory may be completely freed at the OS level, or used for a purpose for which you \
cannot read the memory, at which point you will get a crash.</div>

<div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div \
dir="ltr"><div><span style="color:rgb(255,0,0)"><span \
style="color:rgb(102,102,102)">&gt;&gt;&gt; w.reset_name()<br>

<span style="background-color:rgb(255,255,0)">name before reset_name is \
&lt;stdin&gt;</span><br>

name after reset_name is Epics<br>&gt;&gt;&gt; w.get_name()<br>name before get_name \
is Epics<br>&#39;Epics&#39;</span></span><br><br></div><div>PROBLEMS:<br></div><div>1. \
It won&#39;t print the output when i call<span style="color:rgb(102,102,102)"> \
get_name()</span> after calling <span \
style="color:rgb(102,102,102)">set_name()</span>.<br>


2. As
 you can see in the output, I am editing nothing between the highlighted
 lines, still the output shows <span style="color:rgb(102,102,102)">nothing</span> in \
one while <span style="color:rgb(102,102,102)">&lt;stdin&gt;</span> in  other. \
<br><br>Please tell me what&#39;s wrong.<br> <br></div><div>Looking forward for your \
reply,<br><br></div><div>Sincere Regards,<br></div>Amey Patil</div> \
<br>_______________________________________________<br> PyQt mailing list      <a \
href="mailto:PyQt@riverbankcomputing.com">PyQt@riverbankcomputing.com</a><br> <a \
href="http://www.riverbankcomputing.com/mailman/listinfo/pyqt" \
target="_blank">http://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br></blockquote></div><br></div></div>



[Attachment #6 (text/plain)]

_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic