📄 index.lxp@lxpwrap=x8949_252ehtm.htm
字号:
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE>Things sip can't do automatically</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="First Steps with Sip"HREF="a8834.htm"><LINKREL="PREVIOUS"TITLE="Creating .sip files"HREF="x8887.htm"><LINKREL="NEXT"TITLE="Where to look to start writing your own wrappers/bindings"HREF="x9012.htm"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=x8887_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Appendix C. First Steps with Sip</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x9012_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1">Things <BCLASS="COMMAND">sip</B> can't do automatically</A></H1><P>In a lot of cases, <BCLASS="COMMAND">sip</B> needs nothing but a stripped header file to do its work on—but sometimes more is needed.</P><DIVCLASS="SECT2"><H2CLASS="SECT2">Handwritten code</A></H2><P>Look at the cursorPosition method. It does something Python can't do: it returns values via pointer arguments (the two <TTCLASS="VARNAME">int *</TT> parameters) passed to the method, instead of returning a tuple of values.</P><DIVCLASS="NOTE"><BLOCKQUOTECLASS="NOTE"><P><B>Call by reference and call by value: </B>C and C++ (and Visual Basic and a host of other programming languages) have two ways of passing arguments to functions: by reference, or by value. If a function is called with arguments by reference, changing the value of the arguments will change their value outside the function. Python only has call by (object) reference. If an object is mutable, then changing it inside a function, will also change the object outside a function: </P><PRECLASS="PROGRAMLISTING">>>> def f(a):... a.append("bla")... >>> a=["bla"]>>> f(a)>>> a['bla', 'bla'] </PRE><P>When you can a Python function with an immutable object like a string or an integer, the value of the reference outside the function won't change:</P><PRECLASS="PROGRAMLISTING">>>> >>> def f(a):... a="b"... >>> a="a">>> f(a)>>> a'a'>>> </PRE><P>That's because the name of the argument and the name of the variable are not aliases, they are two seperate names, that might point to different objects, or to the same. As soon as you assign a new string to the argument, the references no longer point to the same name.</P></BLOCKQUOTE></DIV><PRECLASS="PROGRAMLISTING">%MemberCode // The Python interface returns a tuple. QMultiLineEdit *ptr; if (sipParseArgs(&sipArgsParsed,sipArgs, "m", sipThisObj, sipClass_QMultiLineEdit, &ptr)) { int line, col; ptr -> QMultiLineEdit::cursorPosition(&line,&col); return Py_BuildValue("(ii)",line,col); }%End </PRE><P>However, <BCLASS="COMMAND">sip</B> can't determine whether these pointers contain data being sent to the <TTCLASS="FUNCTION">cursorPosition</TT> function, or data being returned by <TTCLASS="FUNCTION">cursorPosition</TT> to the calling code. Since Python has nothing comparable to a C/C++ pointer, there is no automatic way to generate the wrapper for this method. Inside knowledge of what the code actually does is required to generate wrappers, and the developer has to provide <BCLASS="COMMAND">sip</B> with this knowledge.</P><P>Immediately following the cursorPosition method declaration is a <TTCLASS="FUNCTION">%MemberCode</TT> declaration. This allows the developer to tell <BCLASS="COMMAND">sip</B> how to wrap this function by providing most of the necessary C++ code. The contents of the <TTCLASS="FUNCTION">%Membercode</TT> block is, in fact, C++ code.</P><P>Looking at the <TTCLASS="FUNCTION">%Membercode</TT> block, <BCLASS="COMMAND">sip</B> is instructed to first parse the arguments which Python will pass to the wrapper code. The <TTCLASS="FUNCTION">sipParseArgs</TT> function is the most important, and complex, function in the <BCLASS="COMMAND">sip</B> library. The third parameter is a string that encodes the number and types of the Python parameters that are expected, with more information given in later parameters. In this case the <TTCLASS="FUNCTION">sipParseArgs</TT> is being told to expect exactly one Python parameter which is a Python instance of the <TTCLASS="CLASSNAME">QMultiLineEdit</TT> class which corresponds to the value of <TTCLASS="FUNCTION">self</TT>.</P><P>Next, some variables are defined (<TTCLASS="VARNAME">line</TT>, <TTCLASS="VARNAME">col</TT>) to hold the data <TTCLASS="FUNCTION">cursorPosition</TT> will return. The member next calls the Qt/C++ version of <TTCLASS="CLASSNAME">QMultiLineEdit</TT><TTCLASS="FUNCTION">::cursorPosition</TT>, which will fill in the values pointed to by <TTCLASS="VARNAME">&line</TT> and <TTCLASS="VARNAME">&col</TT>.</P><P>Last, the code uses the <TTCLASS="FUNCTION">Py_BuildValue</TT> to return the <TTCLASS="VARNAME">line</TT> and <TTCLASS="VARNAME">col</TT> values obtained to the Python caller. In this case, since two values are returned, the code places the two values in a tuple which is returned to the Python program that called the method. Even though a Python method can return 2 or more distinct values, C++ can't, and the member code is in the C++ domain.</P><P>If you look at some of the code <BCLASS="COMMAND">sip</B> generates, you'll find it looks very much like the member code generated manually for the cursorPosition method. There will be a number of references to functions or methods which begin with ‘sip' or ‘Py'. The ‘Py'-prefixed calls are to code built into Python itself. Python contains a library of functions used to write wrappers/interfaces for C and C++ code. The ‘sip'-prefixed functions are calls to the <BCLASS="COMMAND">sip</B> library, and occur in all <BCLASS="COMMAND">sip</B>-generated code (including all of PyQt). This is why you need to have the <BCLASS="COMMAND">sip</B> library installed before you can use PyQt, even though you don't need to run the <BCLASS="COMMAND">sip</B> program itself.</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2">Other limitations</A></H2><P>Presently, <BCLASS="COMMAND">sip</B> can't automatically generate code for methods which have parameters or return values with types like <TTCLASS="VARNAME">int&</TT>, <TTCLASS="VARNAME">int*</TT> or <TTCLASS="VARNAME">bool*</TT>.</P><P>In addition, <BCLASS="COMMAND">sip</B> can't directly handle types based on C++ templates. In these cases you have to used the <TTCLASS="FUNCTION">%MappedType</TT> directive to supply your own C++ code to explicitly handle how such types are converted to and from Python objects. You still use the C++ template type in parameters and return values of functions and methods, <BCLASS="COMMAND">sip</B> will automatically carry out the necessary conversions based on the C++ code you provided.</P></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><A accesskey="P" href="index.lxp@lxpwrap=x8887_252ehtm.htm">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="H" href="index.lxp@lxpwrap=book1_252ehtm">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><A accesskey="N" href="index.lxp@lxpwrap=x9012_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Creating .sip files</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=a8834_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Where to look to start writing your own wrappers/bindings</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -