././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1643722416.6855206 PyQt6_sip-13.2.1/0000755000076500000240000000000000000000000012254 5ustar00philstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/LICENSE0000644000076500000240000000531600000000000013266 0ustar00philstaffRIVERBANK COMPUTING LIMITED LICENSE AGREEMENT FOR SIP 1. This LICENSE AGREEMENT ("the SIP License") is between Riverbank Computing Limited ("Riverbank"), and the Individual or Organization ("Licensee") accessing and otherwise using SIP software in source or binary form and its associated documentation. SIP comprises a software tool for generating Python bindings for software C and C++ libraries, and a Python extension module used at runtime by those generated bindings. This License Agreement may also be applied to other software packages written by Riverbank. 2. Subject to the terms and conditions of this License Agreement, Riverbank hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use SIP alone or in any derivative version, provided, however, that Riverbank's License Agreement and Riverbank's notice of copyright, e.g., "Copyright (c) 2015 Riverbank Computing Limited; All Rights Reserved" are retained in SIP alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates SIP or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to SIP. 4. Licensee may not use SIP to generate Python bindings for any C or C++ library for which bindings are already provided by Riverbank. 5. Riverbank is making SIP available to Licensee on an "AS IS" basis. RIVERBANK MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, RIVERBANK MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF SIP WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 6. RIVERBANK SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF SIP FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING SIP, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 7. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 8. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between Riverbank and Licensee. This License Agreement does not grant permission to use Riverbank trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 9. By copying, installing or otherwise using SIP, Licensee agrees to be bound by the terms and conditions of this License Agreement. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/LICENSE-GPL20000644000076500000240000004336100000000000013772 0ustar00philstaff------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/LICENSE-GPL30000644000076500000240000010474100000000000013773 0ustar00philstaff------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/MANIFEST.in0000644000076500000240000000006400000000000014012 0ustar00philstaffinclude *.h include bool.cpp include pyproject.toml ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1643722416.6856005 PyQt6_sip-13.2.1/PKG-INFO0000644000076500000240000000077100000000000013356 0ustar00philstaffMetadata-Version: 2.1 Name: PyQt6_sip Version: 13.2.1 Summary: The sip module support for PyQt6 Home-page: https://www.riverbankcomputing.com/software/sip/ Author: Riverbank Computing Limited Author-email: info@riverbankcomputing.com License: SIP Platform: X11 Platform: macOS Platform: Windows Requires-Python: >=3.6 License-File: LICENSE License-File: LICENSE-GPL3 License-File: LICENSE-GPL2 sip Extension Module ==================== The sip extension module provides support for the PyQt6 package. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1643722416.6853337 PyQt6_sip-13.2.1/PyQt6_sip.egg-info/0000755000076500000240000000000000000000000015604 5ustar00philstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/PyQt6_sip.egg-info/PKG-INFO0000644000076500000240000000077100000000000016706 0ustar00philstaffMetadata-Version: 2.1 Name: PyQt6-sip Version: 13.2.1 Summary: The sip module support for PyQt6 Home-page: https://www.riverbankcomputing.com/software/sip/ Author: Riverbank Computing Limited Author-email: info@riverbankcomputing.com License: SIP Platform: X11 Platform: macOS Platform: Windows Requires-Python: >=3.6 License-File: LICENSE License-File: LICENSE-GPL3 License-File: LICENSE-GPL2 sip Extension Module ==================== The sip extension module provides support for the PyQt6 package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/PyQt6_sip.egg-info/SOURCES.txt0000644000076500000240000000050700000000000017472 0ustar00philstaffLICENSE LICENSE-GPL2 LICENSE-GPL3 MANIFEST.in README array.c array.h bool.cpp descriptors.c int_convertors.c objmap.c pyproject.toml setup.cfg setup.py sip.h sipint.h siplib.c threads.c voidptr.c PyQt6_sip.egg-info/PKG-INFO PyQt6_sip.egg-info/SOURCES.txt PyQt6_sip.egg-info/dependency_links.txt PyQt6_sip.egg-info/top_level.txt././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/PyQt6_sip.egg-info/dependency_links.txt0000644000076500000240000000000100000000000021652 0ustar00philstaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/PyQt6_sip.egg-info/top_level.txt0000644000076500000240000000000600000000000020332 0ustar00philstaffPyQt6 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/README0000644000076500000240000000015400000000000013134 0ustar00philstaffsip Extension Module ==================== The sip extension module provides support for the PyQt6 package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/array.c0000644000076500000240000004142100000000000013540 0ustar00philstaff/* * This file implements the API for the array type. * * Copyright (c) 2021 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include "sipint.h" #include "array.h" /* The object data structure. */ typedef struct { PyObject_HEAD void *data; const sipTypeDef *td; const char *format; size_t stride; Py_ssize_t len; int flags; PyObject *owner; } sipArrayObject; static int check_writable(sipArrayObject *array); static int check_index(sipArrayObject *array, Py_ssize_t idx); static void *get_value(sipArrayObject *array, PyObject *value); static void *get_slice(sipArrayObject *array, PyObject *value, Py_ssize_t len); static void bad_key(PyObject *key); static void *element(sipArrayObject *array, Py_ssize_t idx); static PyObject *make_array(void *data, const sipTypeDef *td, const char *format, size_t stride, Py_ssize_t len, int flags, PyObject *owner); /* * Implement len() for the type. */ static Py_ssize_t sipArray_length(PyObject *self) { return ((sipArrayObject *)self)->len; } /* * Implement sequence item sub-script for the type. */ static PyObject *sipArray_item(PyObject *self, Py_ssize_t idx) { sipArrayObject *array = (sipArrayObject *)self; PyObject *py_item; void *data; if (check_index(array, idx) < 0) return NULL; data = element(array, idx); if (array->td != NULL) { py_item = sip_api_convert_from_type(data, array->td, NULL); } else { switch (*array->format) { case 'b': py_item = PyLong_FromLong(*(char *)data); break; case 'B': py_item = PyLong_FromUnsignedLong(*(unsigned char *)data); break; case 'h': py_item = PyLong_FromLong(*(short *)data); break; case 'H': py_item = PyLong_FromUnsignedLong(*(unsigned short *)data); break; case 'i': py_item = PyLong_FromLong(*(int *)data); break; case 'I': py_item = PyLong_FromUnsignedLong(*(unsigned int *)data); break; case 'f': py_item = PyFloat_FromDouble(*(float *)data); break; case 'd': py_item = PyFloat_FromDouble(*(double *)data); break; default: py_item = NULL; } } return py_item; } /* The sequence methods data structure. */ static PySequenceMethods sipArray_SequenceMethods = { sipArray_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ sipArray_item, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; /* * Implement mapping sub-script for the type. */ static PyObject *sipArray_subscript(PyObject *self, PyObject *key) { sipArrayObject *array = (sipArrayObject *)self; if (PyIndex_Check(key)) { Py_ssize_t idx = PyNumber_AsSsize_t(key, PyExc_IndexError); if (idx == -1 && PyErr_Occurred()) return NULL; if (idx < 0) idx += array->len; return sipArray_item(self, idx); } if (PySlice_Check(key)) { Py_ssize_t start, stop, step, slicelength; if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &slicelength) < 0) return NULL; if (step != 1) { PyErr_SetNone(PyExc_NotImplementedError); return NULL; } return make_array(element(array->data, start), array->td, array->format, array->stride, slicelength, (array->flags & ~SIP_OWNS_MEMORY), array->owner); } bad_key(key); return NULL; } /* * Implement mapping assignment sub-script for the type. */ static int sipArray_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { sipArrayObject *array = (sipArrayObject *)self; Py_ssize_t start, len; void *value_data; if (check_writable(array) < 0) return -1; if (PyIndex_Check(key)) { start = PyNumber_AsSsize_t(key, PyExc_IndexError); if (start == -1 && PyErr_Occurred()) return -1; if (start < 0) start += array->len; if (check_index(array, start) < 0) return -1; if ((value_data = get_value(array, value)) == NULL) return -1; len = 1; } else if (PySlice_Check(key)) { Py_ssize_t stop, step; if (sip_api_convert_from_slice_object(key, array->len, &start, &stop, &step, &len) < 0) return -1; if (step != 1) { PyErr_SetNone(PyExc_NotImplementedError); return -1; } if ((value_data = get_slice(array, value, len)) == NULL) return -1; } else { bad_key(key); return -1; } memmove(element(array, start), value_data, len * array->stride); return 0; } /* The mapping methods data structure. */ static PyMappingMethods sipArray_MappingMethods = { sipArray_length, /* mp_length */ sipArray_subscript, /* mp_subscript */ sipArray_ass_subscript, /* mp_ass_subscript */ }; /* * The buffer implementation. */ static int sipArray_getbuffer(PyObject *self, Py_buffer *view, int flags) { sipArrayObject *array = (sipArrayObject *)self; if (view == NULL) return 0; if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) && (array->flags & SIP_READ_ONLY)) { PyErr_SetString(PyExc_BufferError, "object is not writable."); return -1; } view->obj = self; Py_INCREF(self); view->buf = array->data; view->len = array->len; view->readonly = (array->flags & SIP_READ_ONLY); view->itemsize = array->stride; view->format = NULL; if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) view->format = (char *)array->format; view->ndim = 1; view->shape = NULL; if ((flags & PyBUF_ND) == PyBUF_ND) view->shape = &view->len; view->strides = NULL; if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) view->strides = &view->itemsize; view->suboffsets = NULL; view->internal = NULL; return 0; } /* The buffer methods data structure. */ static PyBufferProcs sipArray_BufferProcs = { sipArray_getbuffer, /* bf_getbuffer */ 0 /* bf_releasebuffer */ }; /* The instance deallocation function. */ static void sipArray_dealloc(PyObject *self) { sipArrayObject *array = (sipArrayObject *)self; if (array->flags & SIP_OWNS_MEMORY) sip_api_free(array->data); else Py_XDECREF(array->owner); } /* The type data structure. */ PyTypeObject sipArray_Type = { PyVarObject_HEAD_INIT(NULL, 0) _SIP_MODULE_FQ_NAME ".array", /* tp_name */ sizeof (sipArrayObject), /* tp_basicsize */ 0, /* tp_itemsize */ sipArray_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ &sipArray_SequenceMethods, /* tp_as_sequence */ &sipArray_MappingMethods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ &sipArray_BufferProcs, /* tp_as_buffer */ #if defined(Py_TPFLAGS_HAVE_NEWBUFFER) Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ #endif 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }; /* * Check that an array is writable. */ static int check_writable(sipArrayObject *array) { if (array->flags & SIP_READ_ONLY) { PyErr_SetString(PyExc_TypeError, _SIP_MODULE_FQ_NAME ".array object is read-only"); return -1; } return 0; } /* * Check that an index is valid for an array. */ static int check_index(sipArrayObject *array, Py_ssize_t idx) { if (idx >= 0 && idx < array->len) return 0; PyErr_SetString(PyExc_IndexError, "index out of bounds"); return -1; } /* * Raise an exception about a bad sub-script key. */ static void bad_key(PyObject *key) { PyErr_Format(PyExc_TypeError, "cannot index a " _SIP_MODULE_FQ_NAME ".array object using '%s'", Py_TYPE(key)->tp_name); } /* * Get the address of an element of an array. */ static void *element(sipArrayObject *array, Py_ssize_t idx) { return (unsigned char *)(array->data) + idx * array->stride; } /* * Get the address of a value that will be copied to an array. */ static void *get_value(sipArrayObject *array, PyObject *value) { static union { signed char s_char_t; unsigned char u_char_t; signed short s_short_t; unsigned short u_short_t; signed int s_int_t; unsigned int u_int_t; float float_t; double double_t; } static_data; void *data; if (array->td != NULL) { int iserr = FALSE; data = sip_api_force_convert_to_type_us(value, array->td, NULL, SIP_NOT_NONE|SIP_NO_CONVERTORS, NULL, NULL, &iserr); } else { PyErr_Clear(); switch (*array->format) { case 'b': static_data.s_char_t = sip_api_long_as_char(value); data = &static_data.s_char_t; break; case 'B': static_data.u_char_t = sip_api_long_as_unsigned_char(value); data = &static_data.u_char_t; break; case 'h': static_data.s_short_t = sip_api_long_as_short(value); data = &static_data.s_short_t; break; case 'H': static_data.u_short_t = sip_api_long_as_unsigned_short(value); data = &static_data.u_short_t; break; case 'i': static_data.s_int_t = sip_api_long_as_int(value); data = &static_data.s_int_t; break; case 'I': static_data.u_int_t = sip_api_long_as_unsigned_int(value); data = &static_data.u_int_t; break; case 'f': static_data.float_t = (float)PyFloat_AsDouble(value); data = &static_data.float_t; break; case 'd': static_data.double_t = PyFloat_AsDouble(value); data = &static_data.double_t; break; default: data = NULL; } if (PyErr_Occurred()) data = NULL; } return data; } /* * Get the address of an value that will be copied to an array slice. */ static void *get_slice(sipArrayObject *array, PyObject *value, Py_ssize_t len) { sipArrayObject *other = (sipArrayObject *)value; if (!PyObject_IsInstance(value, (PyObject *)&sipArray_Type) || array->td != other->td || strcmp(array->format, other->format) != 0) { const char *type; if (array->td != NULL) { type = sipTypeName(array->td); } else { switch (*array->format) { case 'b': type = "char"; break; case 'B': type = "unsigned char"; break; case 'h': type = "short"; break; case 'H': type = "unsigned short"; break; case 'i': type = "int"; break; case 'I': type = "unsigned int"; break; case 'f': type = "float"; break; case 'd': type = "double"; break; default: type = ""; } } PyErr_Format(PyExc_TypeError, "can only assign another array of %s to the slice", type); return NULL; } if (other->len != len) { PyErr_Format(PyExc_TypeError, "the array being assigned must have length %zd", len); return NULL; } if (other->stride == array->stride) { PyErr_Format(PyExc_TypeError, "the array being assigned must have stride %zu", array->stride); return NULL; } return other->data; } /* * Do the work of creating an array. */ static PyObject *make_array(void *data, const sipTypeDef *td, const char *format, size_t stride, Py_ssize_t len, int flags, PyObject *owner) { sipArrayObject *array; if ((array = PyObject_NEW(sipArrayObject, &sipArray_Type)) == NULL) return NULL; array->data = data; array->td = td; array->format = format; array->stride = stride; array->len = len; array->flags = flags; if (flags & SIP_OWNS_MEMORY) { /* This is a borrowed reference to itself. */ array->owner = (PyObject *)array; } else { Py_XINCREF(owner); array->owner = owner; } return (PyObject *)array; } /* * Wrap an array of instances of a fundamental type. At the moment format must * be either "b" (char), "B" (unsigned char), "h" (short), "H" (unsigned * short), "i" (int), "I" (unsigned int), "f" (float) or "d" (double). */ PyObject *sip_api_convert_to_array(void *data, const char *format, Py_ssize_t len, int flags) { size_t stride; if (data == NULL) { Py_INCREF(Py_None); return Py_None; } switch (*format) { case 'b': stride = sizeof (char); break; case 'B': stride = sizeof (unsigned char); break; case 'h': stride = sizeof (short); break; case 'H': stride = sizeof (unsigned short); break; case 'i': stride = sizeof (int); break; case 'I': stride = sizeof (unsigned int); break; case 'f': stride = sizeof (float); break; case 'd': stride = sizeof (double); break; default: stride = 0; } assert(stride > 0); assert(len >= 0); return make_array(data, NULL, format, stride, len, flags, NULL); } /* * Wrap an array of instances of a defined type. */ PyObject *sip_api_convert_to_typed_array(void *data, const sipTypeDef *td, const char *format, size_t stride, Py_ssize_t len, int flags) { if (data == NULL) { Py_INCREF(Py_None); return Py_None; } assert(stride > 0); assert(len >= 0); return make_array(data, td, format, stride, len, flags, NULL); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/array.h0000644000076500000240000000214000000000000013540 0ustar00philstaff/* * This file defines the API for the array type. * * Copyright (c) 2019 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _ARRAY_H #define _ARRAY_H #include #include "sipint.h" #ifdef __cplusplus extern "C" { #endif extern PyTypeObject sipArray_Type; PyObject *sip_api_convert_to_array(void *data, const char *format, Py_ssize_t len, int flags); PyObject *sip_api_convert_to_typed_array(void *data, const sipTypeDef *td, const char *format, size_t stride, Py_ssize_t len, int flags); #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/bool.cpp0000644000076500000240000000151700000000000013717 0ustar00philstaff// This contains all the C++ code that is needed by the sip module. // // Copyright (c) 2015 Riverbank Computing Limited // // This file is part of SIP. // // This copy of SIP is licensed for use under the terms of the SIP License // Agreement. See the file LICENSE for more details. // // This copy of SIP may also used under the terms of the GNU General Public // License v2 or v3 as published by the Free Software Foundation which can be // found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. // // SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // Set a C++ bool for the main C implementation of the module. extern "C" void sipSetBool(void *ptr, int val) { *reinterpret_cast(ptr) = !!val; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/descriptors.c0000644000076500000240000003307600000000000014772 0ustar00philstaff/* * The implementation of the different descriptors. * * Copyright (c) 2019 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include "sipint.h" /***************************************************************************** * A method descriptor. We don't use the similar Python descriptor because it * doesn't support a method having static and non-static overloads, and we * handle mixins via a delegate. *****************************************************************************/ /* Forward declarations of slots. */ static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj, PyObject *type); static PyObject *sipMethodDescr_repr(PyObject *self); static int sipMethodDescr_traverse(PyObject *self, visitproc visit, void *arg); static int sipMethodDescr_clear(PyObject *self); static void sipMethodDescr_dealloc(PyObject *self); /* * The object data structure. */ typedef struct _sipMethodDescr { PyObject_HEAD /* The method definition. */ PyMethodDef *pmd; /* The mixin name, if any. */ PyObject *mixin_name; } sipMethodDescr; /* * The type data structure. */ PyTypeObject sipMethodDescr_Type = { PyVarObject_HEAD_INIT(NULL, 0) "sip.methoddescriptor", /* tp_name */ sizeof (sipMethodDescr), /* tp_basicsize */ 0, /* tp_itemsize */ sipMethodDescr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ sipMethodDescr_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ sipMethodDescr_traverse,/* tp_traverse */ sipMethodDescr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ sipMethodDescr_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }; /* * Return a new method descriptor for the given method. */ PyObject *sipMethodDescr_New(PyMethodDef *pmd) { PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0); if (descr != NULL) { ((sipMethodDescr *)descr)->pmd = pmd; ((sipMethodDescr *)descr)->mixin_name = NULL; } return descr; } /* * Return a new method descriptor based on an existing one and a mixin name. */ PyObject *sipMethodDescr_Copy(PyObject *orig, PyObject *mixin_name) { PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0); if (descr != NULL) { ((sipMethodDescr *)descr)->pmd = ((sipMethodDescr *)orig)->pmd; ((sipMethodDescr *)descr)->mixin_name = mixin_name; Py_INCREF(mixin_name); } return descr; } /* * The descriptor's descriptor get slot. */ static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj, PyObject *type) { sipMethodDescr *md = (sipMethodDescr *)self; PyObject *bind, *func; if (obj == NULL) { /* The argument parser must work out that 'self' is the type object. */ bind = type; Py_INCREF(bind); } else if (md->mixin_name != NULL) { bind = PyObject_GetAttr(obj, md->mixin_name); } else { /* * The argument parser must work out that 'self' is the instance * object. */ bind = obj; Py_INCREF(bind); } func = PyCFunction_New(md->pmd, bind); Py_DECREF(bind); return func; } /* * The descriptor's repr slot. This is for the benefit of cProfile which seems * to determine attribute names differently to the rest of Python. */ static PyObject *sipMethodDescr_repr(PyObject *self) { sipMethodDescr *md = (sipMethodDescr *)self; return PyUnicode_FromFormat("", md->pmd->ml_name); } /* * The descriptor's traverse slot. */ static int sipMethodDescr_traverse(PyObject *self, visitproc visit, void *arg) { if (((sipMethodDescr *)self)->mixin_name != NULL) { int vret = visit(((sipMethodDescr *)self)->mixin_name, arg); if (vret != 0) return vret; } return 0; } /* * The descriptor's clear slot. */ static int sipMethodDescr_clear(PyObject *self) { PyObject *tmp = ((sipMethodDescr *)self)->mixin_name; ((sipMethodDescr *)self)->mixin_name = NULL; Py_XDECREF(tmp); return 0; } /* * The descriptor's dealloc slot. */ static void sipMethodDescr_dealloc(PyObject *self) { sipMethodDescr_clear(self); Py_TYPE(self)->tp_free(self); } /***************************************************************************** * A variable descriptor. We don't use the similar Python descriptor because * it doesn't support static variables. *****************************************************************************/ /* Forward declarations of slots. */ static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj, PyObject *type); static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj, PyObject *value); static int sipVariableDescr_traverse(PyObject *self, visitproc visit, void *arg); static int sipVariableDescr_clear(PyObject *self); static void sipVariableDescr_dealloc(PyObject *self); /* * The object data structure. */ typedef struct _sipVariableDescr { PyObject_HEAD /* The getter/setter definition. */ sipVariableDef *vd; /* The generated type definition. */ const sipTypeDef *td; /* The generated container definition. */ const sipContainerDef *cod; /* The mixin name, if any. */ PyObject *mixin_name; } sipVariableDescr; /* * The type data structure. */ PyTypeObject sipVariableDescr_Type = { PyVarObject_HEAD_INIT(NULL, 0) "sip.variabledescriptor", /* tp_name */ sizeof (sipVariableDescr), /* tp_basicsize */ 0, /* tp_itemsize */ sipVariableDescr_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ sipVariableDescr_traverse, /* tp_traverse */ sipVariableDescr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ sipVariableDescr_descr_get, /* tp_descr_get */ sipVariableDescr_descr_set, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }; /* Forward declarations. */ static int get_instance_address(sipVariableDescr *vd, PyObject *obj, void **addrp); /* * Return a new method descriptor for the given getter/setter. */ PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td, const sipContainerDef *cod) { PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0); if (descr != NULL) { ((sipVariableDescr *)descr)->vd = vd; ((sipVariableDescr *)descr)->td = td; ((sipVariableDescr *)descr)->cod = cod; ((sipVariableDescr *)descr)->mixin_name = NULL; } return descr; } /* * Return a new variable descriptor based on an existing one and a mixin name. */ PyObject *sipVariableDescr_Copy(PyObject *orig, PyObject *mixin_name) { PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0); if (descr != NULL) { ((sipVariableDescr *)descr)->vd = ((sipVariableDescr *)orig)->vd; ((sipVariableDescr *)descr)->td = ((sipVariableDescr *)orig)->td; ((sipVariableDescr *)descr)->cod = ((sipVariableDescr *)orig)->cod; ((sipVariableDescr *)descr)->mixin_name = mixin_name; Py_INCREF(mixin_name); } return descr; } /* * The descriptor's descriptor get slot. */ static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj, PyObject *type) { sipVariableDescr *vd = (sipVariableDescr *)self; void *addr; if (get_instance_address(vd, obj, &addr) < 0) return NULL; return ((sipVariableGetterFunc)vd->vd->vd_getter)(addr, obj, type); } /* * The descriptor's descriptor set slot. */ static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj, PyObject *value) { sipVariableDescr *vd = (sipVariableDescr *)self; void *addr; /* Check that the value isn't const. */ if (vd->vd->vd_setter == NULL) { PyErr_Format(PyExc_AttributeError, "'%s' object attribute '%s' is read-only", sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name); return -1; } if (get_instance_address(vd, obj, &addr) < 0) return -1; return ((sipVariableSetterFunc)vd->vd->vd_setter)(addr, value, obj); } /* * Return the C/C++ address of any instance. */ static int get_instance_address(sipVariableDescr *vd, PyObject *obj, void **addrp) { void *addr; if (vd->vd->vd_type == ClassVariable) { addr = NULL; } else { /* Check that access was via an instance. */ if (obj == NULL || obj == Py_None) { PyErr_Format(PyExc_AttributeError, "'%s' object attribute '%s' is an instance attribute", sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name); return -1; } if (vd->mixin_name != NULL) obj = PyObject_GetAttr(obj, vd->mixin_name); /* Get the C++ instance. */ if ((addr = sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, vd->td)) == NULL) return -1; } *addrp = addr; return 0; } /* * The descriptor's traverse slot. */ static int sipVariableDescr_traverse(PyObject *self, visitproc visit, void *arg) { if (((sipVariableDescr *)self)->mixin_name != NULL) { int vret = visit(((sipVariableDescr *)self)->mixin_name, arg); if (vret != 0) return vret; } return 0; } /* * The descriptor's clear slot. */ static int sipVariableDescr_clear(PyObject *self) { PyObject *tmp = ((sipVariableDescr *)self)->mixin_name; ((sipVariableDescr *)self)->mixin_name = NULL; Py_XDECREF(tmp); return 0; } /* * The descriptor's dealloc slot. */ static void sipVariableDescr_dealloc(PyObject *self) { sipVariableDescr_clear(self); Py_TYPE(self)->tp_free(self); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/int_convertors.c0000644000076500000240000001276700000000000015513 0ustar00philstaff/* * The implementation of the Python object to C/C++ integer convertors. * * Copyright (c) 2020 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include "sipint.h" static long long long_as_long_long(PyObject *o, long long min, long long max); static unsigned long long_as_unsigned_long(PyObject *o, unsigned long max); static void raise_signed_overflow(long long min, long long max); static void raise_unsigned_overflow(unsigned long long max); /* * Convert a Python object to a C++ bool (returned as an int). */ int sip_api_convert_to_bool(PyObject *o) { int v; /* Convert the object to an int while checking for overflow. */ v = sip_api_long_as_int(o); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); /* The value must have been non-zero. */ v = 1; } else { PyErr_Format(PyExc_TypeError, "a 'bool' is expected not '%s'", Py_TYPE(o)->tp_name); v = -1; } } else if (v != 0) { v = 1; } return v; } /* * Convert a Python object to a C char. */ char sip_api_long_as_char(PyObject *o) { return (char)long_as_long_long(o, CHAR_MIN, CHAR_MAX); } /* * Convert a Python object to a C signed char. */ signed char sip_api_long_as_signed_char(PyObject *o) { return (signed char)long_as_long_long(o, SCHAR_MIN, SCHAR_MAX); } /* * Convert a Python object to a C unsigned char. */ unsigned char sip_api_long_as_unsigned_char(PyObject *o) { return (unsigned char)long_as_unsigned_long(o, UCHAR_MAX); } /* * Convert a Python object to a C short. */ short sip_api_long_as_short(PyObject *o) { return (short)long_as_long_long(o, SHRT_MIN, SHRT_MAX); } /* * Convert a Python object to a C unsigned short. */ unsigned short sip_api_long_as_unsigned_short(PyObject *o) { return (unsigned short)long_as_unsigned_long(o, USHRT_MAX); } /* * Convert a Python object to a C int. */ int sip_api_long_as_int(PyObject *o) { return (int)long_as_long_long(o, INT_MIN, INT_MAX); } /* * Convert a Python object to a C unsigned int. */ unsigned sip_api_long_as_unsigned_int(PyObject *o) { return (unsigned)long_as_unsigned_long(o, UINT_MAX); } /* * Convert a Python object to a C size_t. */ size_t sip_api_long_as_size_t(PyObject *o) { return (size_t)long_as_unsigned_long(o, SIZE_MAX); } /* * Convert a Python object to a C long. */ long sip_api_long_as_long(PyObject *o) { return (long)long_as_long_long(o, LONG_MIN, LONG_MAX); } /* * Convert a Python object to a C unsigned long. */ unsigned long sip_api_long_as_unsigned_long(PyObject *o) { return long_as_unsigned_long(o, ULONG_MAX); } /* * Convert a Python object to a C long long. */ long long sip_api_long_as_long_long(PyObject *o) { return long_as_long_long(o, LLONG_MIN, LLONG_MAX); } /* * Convert a Python object to a C unsigned long long. */ unsigned long long sip_api_long_as_unsigned_long_long(PyObject *o) { unsigned long long value; PyErr_Clear(); value = PyLong_AsUnsignedLongLong(o); if (PyErr_Occurred()) { /* Provide a better exception message. */ if (PyErr_ExceptionMatches(PyExc_OverflowError)) raise_unsigned_overflow(ULLONG_MAX); } return value; } /* * Convert a Python object to a long long checking that the value is within a * range if overflow checking is enabled. */ static long long long_as_long_long(PyObject *o, long long min, long long max) { long long value; PyErr_Clear(); value = PyLong_AsLongLong(o); if (PyErr_Occurred()) { /* Provide a better exception message. */ if (PyErr_ExceptionMatches(PyExc_OverflowError)) raise_signed_overflow(min, max); } else if (value < min || value > max) { raise_signed_overflow(min, max); } return value; } /* * Convert a Python object to an unsigned long checking that the value is * within a range if overflow checking is enabled. */ static unsigned long long_as_unsigned_long(PyObject *o, unsigned long max) { unsigned long value; PyErr_Clear(); value = PyLong_AsUnsignedLong(o); if (PyErr_Occurred()) { /* Provide a better exception message. */ if (PyErr_ExceptionMatches(PyExc_OverflowError)) raise_unsigned_overflow(max); } else if (value > max) { raise_unsigned_overflow(max); } return value; } /* * Raise an overflow exception if a signed value is out of range. */ static void raise_signed_overflow(long long min, long long max) { PyErr_Format(PyExc_OverflowError, "value must be in the range %lld to %lld", min, max); } /* * Raise an overflow exception if an unsigned value is out of range. */ static void raise_unsigned_overflow(unsigned long long max) { PyErr_Format(PyExc_OverflowError, "value must be in the range 0 to %llu", max); } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/objmap.c0000644000076500000240000003274100000000000013677 0ustar00philstaff/* * This module implements a hash table class for mapping C/C++ addresses to the * corresponding wrapped Python object. * * Copyright (c) 2022 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include "sipint.h" #define hash_1(k,s) (((unsigned long)(k)) % (s)) #define hash_2(k,s) ((s) - 2 - (hash_1((k),(s)) % ((s) - 2))) /* Prime numbers to use as hash table sizes. */ static unsigned long hash_primes[] = { 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827, 2147483659U,0 }; static sipHashEntry *newHashTable(unsigned long); static sipHashEntry *findHashEntry(sipObjectMap *,void *); static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val); static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd); static void reorganiseMap(sipObjectMap *om); static void *getUnguardedPointer(sipSimpleWrapper *w); /* * Initialise an object map. */ void sipOMInit(sipObjectMap *om) { om -> primeIdx = 0; om -> unused = om -> size = hash_primes[om -> primeIdx]; om -> stale = 0; om -> hash_array = newHashTable(om -> size); } /* * Finalise an object map. */ void sipOMFinalise(sipObjectMap *om) { sip_api_free(om -> hash_array); } /* * Allocate and initialise a new hash table. */ static sipHashEntry *newHashTable(unsigned long size) { size_t nbytes; sipHashEntry *hashtab; nbytes = sizeof (sipHashEntry) * size; if ((hashtab = (sipHashEntry *)sip_api_malloc(nbytes)) != NULL) memset(hashtab,0,nbytes); return hashtab; } /* * Return a pointer to the hash entry that is used, or should be used, for the * given C/C++ address. */ static sipHashEntry *findHashEntry(sipObjectMap *om,void *key) { unsigned long hash, inc; void *hek; hash = hash_1(key,om -> size); inc = hash_2(key,om -> size); while ((hek = om -> hash_array[hash].key) != NULL && hek != key) hash = (hash + inc) % om -> size; return &om -> hash_array[hash]; } /* * Return the wrapped Python object of a specific type for a C/C++ address or * NULL if it wasn't found. */ sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, const sipTypeDef *td) { sipHashEntry *he = findHashEntry(om, key); sipSimpleWrapper *sw; PyTypeObject *py_type = sipTypeAsPyTypeObject(td); /* Go through each wrapped object at this address. */ for (sw = he->first; sw != NULL; sw = sw->next) { sipSimpleWrapper *unaliased; unaliased = (sipIsAlias(sw) ? (sipSimpleWrapper *)sw->data : sw); /* * If the reference count is 0 then it is in the process of being * deleted, so ignore it. It's not completely clear how this can * happen (but it can) because it implies that the garbage collection * code is being re-entered (and there are guards in place to prevent * this). */ if (Py_REFCNT(unaliased) == 0) continue; /* Ignore it if the C/C++ address is no longer valid. */ if (sip_api_get_address(unaliased) == NULL) continue; /* * If this wrapped object is of the given type, or a sub-type of it, * then we assume it is the same C++ object. */ if (PyObject_TypeCheck(unaliased, py_type)) return unaliased; } return NULL; } /* * Add a C/C++ address and the corresponding wrapped Python object to the map. */ void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val) { void *addr = getUnguardedPointer(val); const sipClassTypeDef *base_ctd; /* Add the object. */ add_object(om, addr, val); /* Add any aliases. */ base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->wt_td; add_aliases(om, addr, val, base_ctd, base_ctd); } /* * Add an alias for any address that is different when cast to a super-type. */ static void add_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) { const sipEncodedTypeDef *sup; /* See if there are any super-classes. */ if ((sup = ctd->ctd_supers) != NULL) { sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); /* Recurse up the hierachy for the first super-class. */ add_aliases(om, addr, val, base_ctd, sup_ctd); /* * We only check for aliases for subsequent super-classes because the * first one can never need one. */ while (!sup++->sc_flag) { void *sup_addr; sup_ctd = sipGetGeneratedClassType(sup, ctd); /* Recurse up the hierachy for the remaining super-classes. */ add_aliases(om, addr, val, base_ctd, sup_ctd); sup_addr = (*base_ctd->ctd_cast)(addr, (sipTypeDef *)sup_ctd); if (sup_addr != addr) { sipSimpleWrapper *alias; /* Note that we silently ignore errors. */ if ((alias = sip_api_malloc(sizeof (sipSimpleWrapper))) != NULL) { /* * An alias is basically a bit-wise copy of the Python * object but only to ensure the fields we are subverting * are in the right place. An alias should never be passed * to the Python API. */ *alias = *val; alias->sw_flags = (val->sw_flags & SIP_SHARE_MAP) | SIP_ALIAS; alias->data = val; alias->next = NULL; add_object(om, sup_addr, alias); } } } } } /* * Add a wrapper (which may be an alias) to the map. */ static void add_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) { sipHashEntry *he = findHashEntry(om, addr); /* * If the bucket is in use then we appear to have several objects at the * same address. */ if (he->first != NULL) { /* * This can happen for three reasons. A variable of one class can be * declared at the start of another class. Therefore there are two * objects, of different classes, with the same address. The second * reason is that the old C/C++ object has been deleted by C/C++ but we * didn't get to find out for some reason, and a new C/C++ instance has * been created at the same address. The third reason is if we are in * the process of deleting a Python object but the C++ object gets * wrapped again because the C++ dtor called a method that has been * re-implemented in Python. The absence of the SIP_SHARE_MAP flag * tells us that a new C++ instance has just been created and so we * know the second reason is the correct one so we mark the old * pointers as invalid and reuse the entry. Otherwise we just add this * one to the existing list of objects at this address. */ if (!(val->sw_flags & SIP_SHARE_MAP)) { sipSimpleWrapper *sw = he->first; he->first = NULL; while (sw != NULL) { sipSimpleWrapper *next = sw->next; if (sipIsAlias(sw)) { sip_api_free(sw); } else { /* * We are removing it from the map here. We first have to * call the destructor as the destructor itself might end * up trying to remove the wrapper and its aliases from the * map. */ sip_api_instance_destroyed(sw); } sw = next; } } val->next = he->first; he->first = val; return; } /* See if the bucket was unused or stale. */ if (he->key == NULL) { he->key = addr; om->unused--; } else { om->stale--; } /* Add the rest of the new value. */ he->first = val; val->next = NULL; reorganiseMap(om); } /* * Reorganise a map if it is running short of space. */ static void reorganiseMap(sipObjectMap *om) { unsigned long old_size, i; sipHashEntry *ohe, *old_tab; /* Don't bother if it still has more than 12% available. */ if (om -> unused > om -> size >> 3) return; /* * If reorganising (ie. making the stale buckets unused) using the same * sized table would make 25% available then do that. Otherwise use a * bigger table (if possible). */ if (om -> unused + om -> stale < om -> size >> 2 && hash_primes[om -> primeIdx + 1] != 0) om -> primeIdx++; old_size = om -> size; old_tab = om -> hash_array; om -> unused = om -> size = hash_primes[om -> primeIdx]; om -> stale = 0; om -> hash_array = newHashTable(om -> size); /* Transfer the entries from the old table to the new one. */ ohe = old_tab; for (i = 0; i < old_size; ++i) { if (ohe -> key != NULL && ohe -> first != NULL) { *findHashEntry(om,ohe -> key) = *ohe; om -> unused--; } ++ohe; } sip_api_free(old_tab); } /* * Remove a C/C++ object from the table. Return 0 if it was removed * successfully. */ int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val) { void *addr; const sipClassTypeDef *base_ctd; /* Handle the trivial case. */ if (sipNotInMap(val)) return 0; if ((addr = getUnguardedPointer(val)) == NULL) return 0; /* Remove any aliases. */ base_ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(val))->wt_td; remove_aliases(om, addr, val, base_ctd, base_ctd); /* Remove the object. */ return remove_object(om, addr, val); } /* * Remove an alias for any address that is different when cast to a super-type. */ static void remove_aliases(sipObjectMap *om, void *addr, sipSimpleWrapper *val, const sipClassTypeDef *base_ctd, const sipClassTypeDef *ctd) { const sipEncodedTypeDef *sup; /* See if there are any super-classes. */ if ((sup = ctd->ctd_supers) != NULL) { sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); /* Recurse up the hierachy for the first super-class. */ remove_aliases(om, addr, val, base_ctd, sup_ctd); /* * We only check for aliases for subsequent super-classes because the * first one can never need one. */ while (!sup++->sc_flag) { void *sup_addr; sup_ctd = sipGetGeneratedClassType(sup, ctd); /* Recurse up the hierachy for the remaining super-classes. */ remove_aliases(om, addr, val, base_ctd, sup_ctd); sup_addr = (*base_ctd->ctd_cast)(addr, (sipTypeDef *)sup_ctd); if (sup_addr != addr) remove_object(om, sup_addr, val); } } } /* * Remove a wrapper from the map. */ static int remove_object(sipObjectMap *om, void *addr, sipSimpleWrapper *val) { sipHashEntry *he = findHashEntry(om, addr); sipSimpleWrapper **swp; for (swp = &he->first; *swp != NULL; swp = &(*swp)->next) { sipSimpleWrapper *sw, *next; int do_remove; sw = *swp; next = sw->next; if (sipIsAlias(sw)) { if (sw->data == val) { sip_api_free(sw); do_remove = TRUE; } else { do_remove = FALSE; } } else { do_remove = (sw == val); } if (do_remove) { *swp = next; /* * If the bucket is now empty then count it as stale. Note that we * do not NULL the key and count it as unused because that might * throw out the search for another entry that wanted to go here, * found it already occupied, and was put somewhere else. In other * words, searches must be repeatable until we reorganise the * table. */ if (he->first == NULL) om->stale++; return 0; } } return -1; } /* * Return the unguarded pointer to a C/C++ instance, ie. the pointer was valid * but may longer be. */ static void *getUnguardedPointer(sipSimpleWrapper *w) { return (w->access_func != NULL) ? w->access_func(w, UnguardedPointer) : w->data; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/pyproject.toml0000644000076500000240000000007100000000000015166 0ustar00philstaff[build-system] requires = ["setuptools >=30.3", "wheel"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1643722416.6859658 PyQt6_sip-13.2.1/setup.cfg0000644000076500000240000000053500000000000014100 0ustar00philstaff[metadata] description = The sip module support for PyQt6 long_description = file: README author = Riverbank Computing Limited author_email = info@riverbankcomputing.com url = https://www.riverbankcomputing.com/software/sip/ platforms = X11, macOS, Windows [options.package_data] pyqt6.sip = py.types sip.pyi [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/setup.py0000644000076500000240000000313200000000000013765 0ustar00philstaff# Copyright (c) 2020, Riverbank Computing Limited # All rights reserved. # # This copy of SIP is licensed for use under the terms of the SIP License # Agreement. See the file LICENSE for more details. # # This copy of SIP may also used under the terms of the GNU General Public # License v2 or v3 as published by the Free Software Foundation which can be # found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import glob import sys from setuptools import Extension, setup # Build the extension module. module_src = sorted(glob.glob('*.c')) if sys.platform == 'win32': module_src.append('bool.cpp') module = Extension('PyQt6.sip', module_src) # Do the setup. setup( name='PyQt6_sip', version='13.2.1', license='SIP', python_requires='>=3.6', ext_modules=[module] ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/sip.h0000644000076500000240000014031400000000000013223 0ustar00philstaff/* * The SIP module interface. * * Copyright (c) 2022 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _SIP_H #define _SIP_H #include /* Sanity check on the Python version. */ #if PY_VERSION_HEX < 0x03060000 #error "This version of PyQt6.sip requires Python v3.6 or later" #endif #ifdef __cplusplus #include typedef bool (*sipExceptionHandler)(std::exception_ptr); #else typedef void *sipExceptionHandler; #endif #ifdef __cplusplus extern "C" { #endif /* The version of the ABI. */ #define SIP_ABI_MAJOR_VERSION 13 #define SIP_ABI_MINOR_VERSION 2 #define SIP_MODULE_PATCH_VERSION 1 /* * The changes to this version of the ABI. * * v13.2 * - Added support for SIP_ENUM_UINT_ENUM to represent IntEnums with unsigned * members. */ /* The version of the code generator. */ #define SIP_VERSION 0x60501 #define SIP_VERSION_STR "6.5.1" /* These are all dependent on the user-specified name of the sip module. */ #define _SIP_MODULE_FQ_NAME "PyQt6.sip" #define _SIP_MODULE_NAME "sip" #define _SIP_MODULE_SHARED 1 #define _SIP_MODULE_ENTRY PyInit_sip /* * Qt includes this typedef and its meta-object system explicitly converts * types to uint. If these correspond to signal arguments then that conversion * is exposed. Therefore SIP generates code that uses it. This definition is * for the cases that SIP is generating non-Qt related bindings with compilers * that don't include it themselves (i.e. MSVC). */ typedef unsigned int uint; /* Some C++ compatibility stuff. */ #if defined(__cplusplus) /* * Cast a PyCFunctionWithKeywords to a PyCFunction in such a way that it * suppresses the GCC -Wcast-function-type warning. */ #define SIP_MLMETH_CAST(m) reinterpret_cast(reinterpret_cast(m)) #if __cplusplus >= 201103L || defined(_MSVC_LANG) /* C++11 and later. */ #define SIP_NULLPTR nullptr #define SIP_OVERRIDE override #else /* Earlier versions of C++. */ #define SIP_NULLPTR NULL #define SIP_OVERRIDE #endif #else /* Cast a PyCFunctionWithKeywords to a PyCFunction. */ #define SIP_MLMETH_CAST(m) ((PyCFunction)(m)) /* C. */ #define SIP_NULLPTR NULL #define SIP_OVERRIDE #endif /* * The mask that can be passed to sipTrace(). */ #define SIP_TRACE_CATCHERS 0x0001 #define SIP_TRACE_CTORS 0x0002 #define SIP_TRACE_DTORS 0x0004 #define SIP_TRACE_INITS 0x0008 #define SIP_TRACE_DEALLOCS 0x0010 #define SIP_TRACE_METHODS 0x0020 /* * Hide some thread dependent stuff. This can be removed when support for * Python v3.6 is removed. */ #ifdef WITH_THREAD typedef PyGILState_STATE sip_gilstate_t; #define SIP_RELEASE_GIL(gs) PyGILState_Release(gs); #define SIP_BLOCK_THREADS {PyGILState_STATE sipGIL = PyGILState_Ensure(); #define SIP_UNBLOCK_THREADS PyGILState_Release(sipGIL);} #else typedef int sip_gilstate_t; #define SIP_RELEASE_GIL(gs) #define SIP_BLOCK_THREADS #define SIP_UNBLOCK_THREADS #endif /* * Forward declarations of types. */ struct _sipBufferDef; typedef struct _sipBufferDef sipBufferDef; struct _sipBufferInfoDef; typedef struct _sipBufferInfoDef sipBufferInfoDef; struct _sipCFunctionDef; typedef struct _sipCFunctionDef sipCFunctionDef; struct _sipDateDef; typedef struct _sipDateDef sipDateDef; struct _sipMethodDef; typedef struct _sipMethodDef sipMethodDef; struct _sipSimpleWrapper; typedef struct _sipSimpleWrapper sipSimpleWrapper; struct _sipTimeDef; typedef struct _sipTimeDef sipTimeDef; struct _sipTypeDef; typedef struct _sipTypeDef sipTypeDef; struct _sipWrapperType; typedef struct _sipWrapperType sipWrapperType; struct _sipWrapper; typedef struct _sipWrapper sipWrapper; /* * The different events a handler can be registered for. */ typedef enum { sipEventWrappedInstance, /* After wrapping a C/C++ instance. */ sipEventCollectingWrapper, /* When garbage collecting a wrapper object. */ sipEventNrEvents } sipEventType; /* * The event handlers. */ typedef void (*sipWrappedInstanceEventHandler)(void *sipCpp); typedef void (*sipCollectingWrapperEventHandler)(sipSimpleWrapper *sipSelf); /* * The operation an access function is being asked to perform. */ typedef enum { UnguardedPointer, /* Return the unguarded pointer. */ GuardedPointer, /* Return the guarded pointer, ie. 0 if it has gone. */ ReleaseGuard /* Release the guard, if any. */ } AccessFuncOp; /* * Some convenient function pointers. */ typedef void *(*sipInitFunc)(sipSimpleWrapper *, PyObject *, PyObject *, PyObject **, PyObject **, PyObject **); typedef int (*sipFinalFunc)(PyObject *, void *, PyObject *, PyObject **); typedef void *(*sipAccessFunc)(sipSimpleWrapper *, AccessFuncOp); typedef int (*sipTraverseFunc)(void *, visitproc, void *); typedef int (*sipClearFunc)(void *); typedef int (*sipGetBufferFuncLimited)(PyObject *, void *, sipBufferDef *); typedef void (*sipReleaseBufferFuncLimited)(PyObject *, void *); #if !defined(Py_LIMITED_API) typedef int (*sipGetBufferFunc)(PyObject *, void *, Py_buffer *, int); typedef void (*sipReleaseBufferFunc)(PyObject *, void *, Py_buffer *); #endif typedef void (*sipDeallocFunc)(sipSimpleWrapper *); typedef void *(*sipCastFunc)(void *, const sipTypeDef *); typedef const sipTypeDef *(*sipSubClassConvertFunc)(void **); typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *, void **); typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); typedef void (*sipVirtErrorHandlerFunc)(sipSimpleWrapper *, sip_gilstate_t); typedef int (*sipVirtHandlerFunc)(sip_gilstate_t, sipVirtErrorHandlerFunc, sipSimpleWrapper *, PyObject *, ...); typedef void (*sipAssignFunc)(void *, Py_ssize_t, void *); typedef void *(*sipArrayFunc)(Py_ssize_t); typedef void *(*sipCopyFunc)(const void *, Py_ssize_t); typedef void (*sipReleaseFunc)(void *, int); typedef void (*sipReleaseUSFunc)(void *, int, void *); typedef PyObject *(*sipPickleFunc)(void *); typedef int (*sipAttrGetterFunc)(const sipTypeDef *, PyObject *); typedef PyObject *(*sipVariableGetterFunc)(void *, PyObject *, PyObject *); typedef int (*sipVariableSetterFunc)(void *, PyObject *, PyObject *); typedef void *(*sipProxyResolverFunc)(void *); typedef void (*sipWrapperVisitorFunc)(sipSimpleWrapper *, void *); #if !defined(Py_LIMITED_API) /* * The meta-type of a wrapper type. */ struct _sipWrapperType { /* * The super-metatype. This must be first in the structure so that it can * be cast to a PyTypeObject *. */ PyHeapTypeObject super; /* Set if the type is a user implemented Python sub-class. */ unsigned wt_user_type : 1; /* Set if the type's dictionary contains all lazy attributes. */ unsigned wt_dict_complete : 1; /* Unused and available for future use. */ unsigned wt_unused : 30; /* The generated type structure. */ sipTypeDef *wt_td; /* The list of init extenders. */ struct _sipInitExtenderDef *wt_iextend; /* * For the user to use. Note that any data structure will leak if the * type is garbage collected. */ void *wt_user_data; /* Reserved for future use by this ABI version. */ void *wt_reserved; }; /* * The type of a simple C/C++ wrapper object. */ struct _sipSimpleWrapper { PyObject_HEAD /* * The data, initially a pointer to the C/C++ object, as interpreted by the * access function. */ void *data; /* The optional access function. */ sipAccessFunc access_func; /* Object flags. */ unsigned sw_flags; /* The optional dictionary of extra references keyed by argument number. */ PyObject *extra_refs; /* For the user to use. */ PyObject *user; /* The instance dictionary. */ PyObject *dict; /* The main instance if this is a mixin. */ PyObject *mixin_main; /* Reserved for future use by this ABI version. */ void *reserved; /* Next object at this address. */ struct _sipSimpleWrapper *next; }; /* * The type of a C/C++ wrapper object that supports parent/child relationships. */ struct _sipWrapper { /* The super-type. */ sipSimpleWrapper super; /* First child object. */ struct _sipWrapper *first_child; /* Next sibling. */ struct _sipWrapper *sibling_next; /* Previous sibling. */ struct _sipWrapper *sibling_prev; /* Owning object. */ struct _sipWrapper *parent; }; #endif /* * The information describing an encoded type ID. */ typedef struct _sipEncodedTypeDef { /* The type number. */ unsigned sc_type : 16; /* The module number (255 for this one). */ unsigned sc_module : 8; /* A context specific flag. */ unsigned sc_flag : 1; } sipEncodedTypeDef; /* * The information describing static instances. */ typedef struct _sipInstancesDef { /* The types. */ struct _sipTypeInstanceDef *id_type; /* The void *. */ struct _sipVoidPtrInstanceDef *id_voidp; /* The chars. */ struct _sipCharInstanceDef *id_char; /* The strings. */ struct _sipStringInstanceDef *id_string; /* The ints. */ struct _sipIntInstanceDef *id_int; /* The longs. */ struct _sipLongInstanceDef *id_long; /* The unsigned longs. */ struct _sipUnsignedLongInstanceDef *id_ulong; /* The long longs. */ struct _sipLongLongInstanceDef *id_llong; /* The unsigned long longs. */ struct _sipUnsignedLongLongInstanceDef *id_ullong; /* The doubles. */ struct _sipDoubleInstanceDef *id_double; } sipInstancesDef; /* * The information describing a type initialiser extender. */ typedef struct _sipInitExtenderDef { /* The extender function. */ sipInitFunc ie_extender; /* The class being extended. */ sipEncodedTypeDef ie_class; /* The next extender for this class. */ struct _sipInitExtenderDef *ie_next; } sipInitExtenderDef; /* * The information describing a sub-class convertor. */ typedef struct _sipSubClassConvertorDef { /* The convertor. */ sipSubClassConvertFunc scc_convertor; /* The encoded base type. */ sipEncodedTypeDef scc_base; /* The base type. */ struct _sipTypeDef *scc_basetype; } sipSubClassConvertorDef; /* * The structure populated by %BIGetBufferCode when the limited API is enabled. */ struct _sipBufferDef { /* The address of the buffer. */ void *bd_buffer; /* The length of the buffer. */ Py_ssize_t bd_length; /* Set if the buffer is read-only. */ int bd_readonly; }; /* * The structure describing a Python buffer. */ struct _sipBufferInfoDef { /* This is internal to sip. */ void *bi_internal; /* The address of the buffer. */ void *bi_buf; /* A reference to the object implementing the buffer interface. */ PyObject *bi_obj; /* The length of the buffer in bytes. */ Py_ssize_t bi_len; /* Set if the buffer is read-only. */ int bi_readonly; /* The format of each element of the buffer. */ char *bi_format; }; /* * The structure describing a Python C function. */ struct _sipCFunctionDef { /* The C function. */ PyMethodDef *cf_function; /* The optional bound object. */ PyObject *cf_self; }; /* * The structure describing a Python method. */ struct _sipMethodDef { /* The function that implements the method. */ PyObject *pm_function; /* The bound object. */ PyObject *pm_self; }; /* * The structure describing a Python date. */ struct _sipDateDef { /* The year. */ int pd_year; /* The month (1-12). */ int pd_month; /* The day (1-31). */ int pd_day; }; /* * The structure describing a Python time. */ struct _sipTimeDef { /* The hour (0-23). */ int pt_hour; /* The minute (0-59). */ int pt_minute; /* The second (0-59). */ int pt_second; /* The microsecond (0-999999). */ int pt_microsecond; }; /* * The different error states of handwritten code. */ typedef enum { sipErrorNone, /* There is no error. */ sipErrorFail, /* The error is a failure. */ sipErrorContinue /* It may not apply if a later operation succeeds. */ } sipErrorState; /* * The different Python slot types. New slots must be added to the end, * otherwise the major version of the internal ABI must be changed. */ typedef enum { str_slot, /* __str__ */ int_slot, /* __int__ */ float_slot, /* __float__ */ len_slot, /* __len__ */ contains_slot, /* __contains__ */ add_slot, /* __add__ for number */ concat_slot, /* __add__ for sequence types */ sub_slot, /* __sub__ */ mul_slot, /* __mul__ for number types */ repeat_slot, /* __mul__ for sequence types */ div_slot, /* __div__ */ mod_slot, /* __mod__ */ floordiv_slot, /* __floordiv__ */ truediv_slot, /* __truediv__ */ and_slot, /* __and__ */ or_slot, /* __or__ */ xor_slot, /* __xor__ */ lshift_slot, /* __lshift__ */ rshift_slot, /* __rshift__ */ iadd_slot, /* __iadd__ for number types */ iconcat_slot, /* __iadd__ for sequence types */ isub_slot, /* __isub__ */ imul_slot, /* __imul__ for number types */ irepeat_slot, /* __imul__ for sequence types */ idiv_slot, /* __idiv__ */ imod_slot, /* __imod__ */ ifloordiv_slot, /* __ifloordiv__ */ itruediv_slot, /* __itruediv__ */ iand_slot, /* __iand__ */ ior_slot, /* __ior__ */ ixor_slot, /* __ixor__ */ ilshift_slot, /* __ilshift__ */ irshift_slot, /* __irshift__ */ invert_slot, /* __invert__ */ call_slot, /* __call__ */ getitem_slot, /* __getitem__ */ setitem_slot, /* __setitem__ */ delitem_slot, /* __delitem__ */ lt_slot, /* __lt__ */ le_slot, /* __le__ */ eq_slot, /* __eq__ */ ne_slot, /* __ne__ */ gt_slot, /* __gt__ */ ge_slot, /* __ge__ */ bool_slot, /* __bool__, __nonzero__ */ neg_slot, /* __neg__ */ repr_slot, /* __repr__ */ hash_slot, /* __hash__ */ pos_slot, /* __pos__ */ abs_slot, /* __abs__ */ index_slot, /* __index__ */ iter_slot, /* __iter__ */ next_slot, /* __next__ */ setattr_slot, /* __setattr__, __delattr__ */ matmul_slot, /* __matmul__ (for Python v3.5 and later) */ imatmul_slot, /* __imatmul__ (for Python v3.5 and later) */ await_slot, /* __await__ (for Python v3.5 and later) */ aiter_slot, /* __aiter__ (for Python v3.5 and later) */ anext_slot, /* __anext__ (for Python v3.5 and later) */ } sipPySlotType; /* * The information describing a Python slot function. */ typedef struct _sipPySlotDef { /* The function. */ void *psd_func; /* The type. */ sipPySlotType psd_type; } sipPySlotDef; /* * The information describing a Python slot extender. */ typedef struct _sipPySlotExtenderDef { /* The function. */ void *pse_func; /* The type. */ sipPySlotType pse_type; /* The encoded class. */ sipEncodedTypeDef pse_class; } sipPySlotExtenderDef; /* * The information describing a typedef. */ typedef struct _sipTypedefDef { /* The typedef name. */ const char *tdd_name; /* The typedef value. */ const char *tdd_type_name; } sipTypedefDef; /* * The information describing a variable or property. */ typedef enum { PropertyVariable, /* A property. */ InstanceVariable, /* An instance variable. */ ClassVariable /* A class (i.e. static) variable. */ } sipVariableType; typedef struct _sipVariableDef { /* The type of variable. */ sipVariableType vd_type; /* The name. */ const char *vd_name; /* * The getter. If this is a variable (rather than a property) then the * actual type is sipVariableGetterFunc. */ PyMethodDef *vd_getter; /* * The setter. If this is a variable (rather than a property) then the * actual type is sipVariableSetterFunc. It is NULL if the property cannot * be set or the variable is const. */ PyMethodDef *vd_setter; /* The property deleter. */ PyMethodDef *vd_deleter; /* The docstring. */ const char *vd_docstring; } sipVariableDef; /* * The information describing a type, either a C++ class (or C struct), a C++ * namespace, a mapped type or a named enum. */ struct _sipTypeDef { /* * The module, 0 if the type hasn't been initialised. */ struct _sipExportedModuleDef *td_module; /* Type flags, see the sipType*() macros. */ int td_flags; /* The C/C++ name of the type. */ int td_cname; /* The Python type object. */ PyTypeObject *td_py_type; /* Any additional fixed data generated by a plugin. */ void *td_plugin_data; }; /* * The information describing a container (ie. a class, namespace or a mapped * type). */ typedef struct _sipContainerDef { /* * The Python name of the type, -1 if this is a namespace extender (in the * context of a class) or doesn't require a namespace (in the context of a * mapped type). */ int cod_name; /* * The scoping type or the namespace this is extending if it is a namespace * extender. */ sipEncodedTypeDef cod_scope; /* The number of lazy methods. */ int cod_nrmethods; /* The table of lazy methods. */ PyMethodDef *cod_methods; /* The number of variables. */ int cod_nrvariables; /* The table of variables. */ sipVariableDef *cod_variables; /* The static instances. */ sipInstancesDef cod_instances; } sipContainerDef; /* * The information describing a C++ class (or C struct) or a C++ namespace. */ typedef struct _sipClassTypeDef { /* The base type information. */ sipTypeDef ctd_base; /* The container information. */ sipContainerDef ctd_container; /* The docstring. */ const char *ctd_docstring; /* * The meta-type name, -1 to use the meta-type of the first super-type * (normally sipWrapperType). */ int ctd_metatype; /* The super-type name, -1 to use sipWrapper. */ int ctd_supertype; /* The super-types. */ sipEncodedTypeDef *ctd_supers; /* The table of Python slots. */ sipPySlotDef *ctd_pyslots; /* The initialisation function. */ sipInitFunc ctd_init; /* The traverse function. */ sipTraverseFunc ctd_traverse; /* The clear function. */ sipClearFunc ctd_clear; /* The get buffer function. */ #if defined(Py_LIMITED_API) sipGetBufferFuncLimited ctd_getbuffer; #else sipGetBufferFunc ctd_getbuffer; #endif /* The release buffer function. */ #if defined(Py_LIMITED_API) sipReleaseBufferFuncLimited ctd_releasebuffer; #else sipReleaseBufferFunc ctd_releasebuffer; #endif /* The deallocation function. */ sipDeallocFunc ctd_dealloc; /* The optional assignment function. */ sipAssignFunc ctd_assign; /* The optional array allocation function. */ sipArrayFunc ctd_array; /* The optional copy function. */ sipCopyFunc ctd_copy; /* The release function, 0 if a C struct. */ sipReleaseFunc ctd_release; /* The cast function, 0 if a C struct. */ sipCastFunc ctd_cast; /* The optional convert to function. */ sipConvertToFunc ctd_cto; /* The optional convert from function. */ sipConvertFromFunc ctd_cfrom; /* The next namespace extender. */ struct _sipClassTypeDef *ctd_nsextender; /* The pickle function. */ sipPickleFunc ctd_pickle; /* The finalisation function. */ sipFinalFunc ctd_final; /* The mixin initialisation function. */ initproc ctd_init_mixin; } sipClassTypeDef; /* * The information describing a mapped type. */ typedef struct _sipMappedTypeDef { /* The base type information. */ sipTypeDef mtd_base; /* The container information. */ sipContainerDef mtd_container; /* The optional assignment function. */ sipAssignFunc mtd_assign; /* The optional array allocation function. */ sipArrayFunc mtd_array; /* The optional copy function. */ sipCopyFunc mtd_copy; /* The optional release function. */ sipReleaseUSFunc mtd_release; /* The optional convert to function. */ sipConvertToFunc mtd_cto; /* The optional convert from function. */ sipConvertFromFunc mtd_cfrom; } sipMappedTypeDef; /* * The information describing a named enum. */ typedef struct _sipEnumTypeDef { /* The base type information. */ sipTypeDef etd_base; /* The Python base type. */ int etd_base_type; /* The Python name of the enum. */ int etd_name; /* The scoping type, -1 if it is defined at the module level. */ int etd_scope; /* The number of members. */ int etd_nr_members; /* The Python slots. */ struct _sipPySlotDef *etd_pyslots; } sipEnumTypeDef; /* * The information describing an external type. */ typedef struct _sipExternalTypeDef { /* The index into the type table. */ int et_nr; /* The name of the type. */ const char *et_name; } sipExternalTypeDef; /* * Defines an entry in the module specific list of delayed dtor calls. */ typedef struct _sipDelayedDtor { /* The C/C++ instance. */ void *dd_ptr; /* The class name. */ const char *dd_name; /* Non-zero if dd_ptr is a derived class instance. */ int dd_isderived; /* Next in the list. */ struct _sipDelayedDtor *dd_next; } sipDelayedDtor; /* * Defines a virtual error handler. */ typedef struct _sipVirtErrorHandlerDef { /* The name of the handler. */ const char *veh_name; /* The handler function. */ sipVirtErrorHandlerFunc veh_handler; } sipVirtErrorHandlerDef; /* * Defines a type imported from another module. */ typedef union _sipImportedTypeDef { /* The type name before the module is imported. */ const char *it_name; /* The type after the module is imported. */ sipTypeDef *it_td; } sipImportedTypeDef; /* * Defines a virtual error handler imported from another module. */ typedef union _sipImportedVirtErrorHandlerDef { /* The handler name before the module is imported. */ const char *iveh_name; /* The handler after the module is imported. */ sipVirtErrorHandlerFunc iveh_handler; } sipImportedVirtErrorHandlerDef; /* * Defines an exception imported from another module. */ typedef union _sipImportedExceptionDef { /* The exception name before the module is imported. */ const char *iexc_name; /* The exception object after the module is imported. */ PyObject *iexc_object; } sipImportedExceptionDef; /* * The information describing an imported module. */ typedef struct _sipImportedModuleDef { /* The module name. */ const char *im_name; /* The types imported from the module. */ sipImportedTypeDef *im_imported_types; /* The virtual error handlers imported from the module. */ sipImportedVirtErrorHandlerDef *im_imported_veh; /* The exceptions imported from the module. */ sipImportedExceptionDef *im_imported_exceptions; } sipImportedModuleDef; /* * The main client module structure. */ typedef struct _sipExportedModuleDef { /* The next in the list. */ struct _sipExportedModuleDef *em_next; /* The SIP API minor version number. */ unsigned em_api_minor; /* The module name. */ int em_name; /* The module name as an object. */ PyObject *em_nameobj; /* The string pool. */ const char *em_strings; /* The imported modules. */ sipImportedModuleDef *em_imports; /* The number of types. */ int em_nrtypes; /* The table of types. */ sipTypeDef **em_types; /* The table of external types. */ sipExternalTypeDef *em_external; /* The number of typedefs. */ int em_nrtypedefs; /* The table of typedefs. */ sipTypedefDef *em_typedefs; /* The table of virtual error handlers. */ sipVirtErrorHandlerDef *em_virterrorhandlers; /* The sub-class convertors. */ sipSubClassConvertorDef *em_convertors; /* The static instances. */ sipInstancesDef em_instances; /* The license. */ struct _sipLicenseDef *em_license; /* The table of exception types. */ PyObject **em_exceptions; /* The table of Python slot extenders. */ sipPySlotExtenderDef *em_slotextend; /* The table of initialiser extenders. */ sipInitExtenderDef *em_initextend; /* The delayed dtor handler. */ void (*em_delayeddtors)(const sipDelayedDtor *); /* The list of delayed dtors. */ sipDelayedDtor *em_ddlist; /* The exception handler. */ sipExceptionHandler em_exception_handler; } sipExportedModuleDef; /* * The information describing a license to be added to a dictionary. */ typedef struct _sipLicenseDef { /* The type of license. */ const char *lc_type; /* The licensee. */ const char *lc_licensee; /* The timestamp. */ const char *lc_timestamp; /* The signature. */ const char *lc_signature; } sipLicenseDef; /* * The information describing a void pointer instance to be added to a * dictionary. */ typedef struct _sipVoidPtrInstanceDef { /* The void pointer name. */ const char *vi_name; /* The void pointer value. */ void *vi_val; } sipVoidPtrInstanceDef; /* * The information describing a char instance to be added to a dictionary. */ typedef struct _sipCharInstanceDef { /* The char name. */ const char *ci_name; /* The char value. */ char ci_val; /* The encoding used, either 'A', 'L', '8' or 'N'. */ char ci_encoding; } sipCharInstanceDef; /* * The information describing a string instance to be added to a dictionary. * This is also used as a hack to add (or fix) other types rather than add a * new table type and so requiring a new major version of the API. */ typedef struct _sipStringInstanceDef { /* The string name. */ const char *si_name; /* The string value. */ const char *si_val; /* * The encoding used, either 'A', 'L', '8' or 'N'. 'w' and 'W' are also * used to support the fix for wchar_t. */ char si_encoding; } sipStringInstanceDef; /* * The information describing an int instance to be added to a dictionary. */ typedef struct _sipIntInstanceDef { /* The int name. */ const char *ii_name; /* The int value. */ int ii_val; } sipIntInstanceDef; /* * The information describing a long instance to be added to a dictionary. */ typedef struct _sipLongInstanceDef { /* The long name. */ const char *li_name; /* The long value. */ long li_val; } sipLongInstanceDef; /* * The information describing an unsigned long instance to be added to a * dictionary. */ typedef struct _sipUnsignedLongInstanceDef { /* The unsigned long name. */ const char *uli_name; /* The unsigned long value. */ unsigned long uli_val; } sipUnsignedLongInstanceDef; /* * The information describing a long long instance to be added to a dictionary. */ typedef struct _sipLongLongInstanceDef { /* The long long name. */ const char *lli_name; /* The long long value. */ long long lli_val; } sipLongLongInstanceDef; /* * The information describing an unsigned long long instance to be added to a * dictionary. */ typedef struct _sipUnsignedLongLongInstanceDef { /* The unsigned long long name. */ const char *ulli_name; /* The unsigned long long value. */ unsigned long long ulli_val; } sipUnsignedLongLongInstanceDef; /* * The information describing a double instance to be added to a dictionary. */ typedef struct _sipDoubleInstanceDef { /* The double name. */ const char *di_name; /* The double value. */ double di_val; } sipDoubleInstanceDef; /* * The information describing a class or enum instance to be added to a * dictionary. */ typedef struct _sipTypeInstanceDef { /* The type instance name. */ const char *ti_name; /* The actual instance. */ void *ti_ptr; /* A pointer to the generated type. */ struct _sipTypeDef **ti_type; /* The wrapping flags. */ int ti_flags; } sipTypeInstanceDef; /* * The API exported by the SIP module, ie. pointers to all the data and * functions that can be used by generated code. */ typedef struct _sipAPIDef { /* * This must be the first entry and it's signature must not change so that * version number mismatches can be detected and reported. */ int (*api_export_module)(sipExportedModuleDef *client, unsigned api_major, unsigned api_minor, void *unused); /* * The following are part of the public API. */ PyTypeObject *api_simplewrapper_type; PyTypeObject *api_wrapper_type; PyTypeObject *api_wrappertype_type; PyTypeObject *api_voidptr_type; void (*api_bad_catcher_result)(PyObject *method); void (*api_bad_length_for_slice)(Py_ssize_t seqlen, Py_ssize_t slicelen); PyObject *(*api_build_result)(int *isErr, const char *fmt, ...); PyObject *(*api_call_method)(int *isErr, PyObject *method, const char *fmt, ...); void (*api_call_procedure_method)(sip_gilstate_t, sipVirtErrorHandlerFunc, sipSimpleWrapper *, PyObject *, const char *, ...); Py_ssize_t (*api_convert_from_sequence_index)(Py_ssize_t idx, Py_ssize_t len); int (*api_can_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, int flags); void *(*api_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp); void *(*api_convert_to_type_us)(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp); void *(*api_force_convert_to_type)(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp); void *(*api_force_convert_to_type_us)(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp); void (*api_release_type)(void *cpp, const sipTypeDef *td, int state); void (*api_release_type_us)(void *cpp, const sipTypeDef *td, int state, void *user_state); PyObject *(*api_convert_from_type)(void *cpp, const sipTypeDef *td, PyObject *transferObj); PyObject *(*api_convert_from_new_type)(void *cpp, const sipTypeDef *td, PyObject *transferObj); PyObject *(*api_convert_from_enum)(int eval, const sipTypeDef *td); int (*api_get_state)(PyObject *transferObj); void (*api_free)(void *mem); PyObject *(*api_get_pyobject)(void *cppPtr, const sipTypeDef *td); void *(*api_malloc)(size_t nbytes); int (*api_parse_result)(int *isErr, PyObject *method, PyObject *res, const char *fmt, ...); void (*api_trace)(unsigned mask, const char *fmt, ...); void (*api_transfer_back)(PyObject *self); void (*api_transfer_to)(PyObject *self, PyObject *owner); unsigned long (*api_long_as_unsigned_long)(PyObject *o); PyObject *(*api_convert_from_void_ptr)(void *val); PyObject *(*api_convert_from_const_void_ptr)(const void *val); PyObject *(*api_convert_from_void_ptr_and_size)(void *val, Py_ssize_t size); PyObject *(*api_convert_from_const_void_ptr_and_size)(const void *val, Py_ssize_t size); void *(*api_convert_to_void_ptr)(PyObject *obj); int (*api_export_symbol)(const char *name, void *sym); void *(*api_import_symbol)(const char *name); const sipTypeDef *(*api_find_type)(const char *type); int (*api_register_py_type)(PyTypeObject *type); const sipTypeDef *(*api_type_from_py_type_object)(PyTypeObject *py_type); const sipTypeDef *(*api_type_scope)(const sipTypeDef *td); const char *(*api_resolve_typedef)(const char *name); int (*api_register_attribute_getter)(const sipTypeDef *td, sipAttrGetterFunc getter); sipErrorState (*api_bad_callable_arg)(int arg_nr, PyObject *arg); void *(*api_get_address)(struct _sipSimpleWrapper *w); int (*api_enable_autoconversion)(const sipTypeDef *td, int enable); void *(*api_get_mixin_address)(struct _sipSimpleWrapper *w, const sipTypeDef *td); PyObject *(*api_convert_from_new_pytype)(void *cpp, PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...); PyObject *(*api_convert_to_typed_array)(void *data, const sipTypeDef *td, const char *format, size_t stride, Py_ssize_t len, int flags); PyObject *(*api_convert_to_array)(void *data, const char *format, Py_ssize_t len, int flags); int (*api_register_proxy_resolver)(const sipTypeDef *td, sipProxyResolverFunc resolver); PyInterpreterState *(*api_get_interpreter)(void); void (*api_set_type_user_data)(sipWrapperType *, void *); void *(*api_get_type_user_data)(const sipWrapperType *); PyObject *(*api_py_type_dict)(const PyTypeObject *); const char *(*api_py_type_name)(const PyTypeObject *); int (*api_get_method)(PyObject *, sipMethodDef *); PyObject *(*api_from_method)(const sipMethodDef *); int (*api_get_c_function)(PyObject *, sipCFunctionDef *); int (*api_get_date)(PyObject *, sipDateDef *); PyObject *(*api_from_date)(const sipDateDef *); int (*api_get_datetime)(PyObject *, sipDateDef *, sipTimeDef *); PyObject *(*api_from_datetime)(const sipDateDef *, const sipTimeDef *); int (*api_get_time)(PyObject *, sipTimeDef *); PyObject *(*api_from_time)(const sipTimeDef *); int (*api_is_user_type)(const sipWrapperType *); int (*api_check_plugin_for_type)(const sipTypeDef *, const char *); PyObject *(*api_unicode_new)(Py_ssize_t, unsigned, int *, void **); void (*api_unicode_write)(int, void *, int, unsigned); void *(*api_unicode_data)(PyObject *, int *, Py_ssize_t *); int (*api_get_buffer_info)(PyObject *, sipBufferInfoDef *); void (*api_release_buffer_info)(sipBufferInfoDef *); PyObject *(*api_get_user_object)(const sipSimpleWrapper *); void (*api_set_user_object)(sipSimpleWrapper *, PyObject *); void (*api_instance_destroyed)(sipSimpleWrapper *sipSelf); int (*api_is_owned_by_python)(sipSimpleWrapper *); int (*api_enable_gc)(int enable); void (*api_print_object)(PyObject *o); int (*api_register_event_handler)(sipEventType type, const sipTypeDef *td, void *handler); int (*api_convert_to_enum)(PyObject *obj, const sipTypeDef *td); int (*api_convert_to_bool)(PyObject *obj); char (*api_long_as_char)(PyObject *o); signed char (*api_long_as_signed_char)(PyObject *o); unsigned char (*api_long_as_unsigned_char)(PyObject *o); short (*api_long_as_short)(PyObject *o); unsigned short (*api_long_as_unsigned_short)(PyObject *o); int (*api_long_as_int)(PyObject *o); unsigned int (*api_long_as_unsigned_int)(PyObject *o); long (*api_long_as_long)(PyObject *o); long long (*api_long_as_long_long)(PyObject *o); unsigned long long (*api_long_as_unsigned_long_long)(PyObject *o); int (*api_convert_from_slice_object)(PyObject *slice, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength); size_t (*api_long_as_size_t)(PyObject *o); void (*api_visit_wrappers)(sipWrapperVisitorFunc visitor, void *closure); int (*api_register_exit_notifier)(PyMethodDef *md); int (*api_is_enum_flag)(PyObject *o); void (*unused_public_1)(void); void (*unused_public_2)(void); void (*unused_public_3)(void); void (*unused_public_4)(void); void (*unused_public_5)(void); /* * The following are not part of the public API. */ int (*api_init_module)(sipExportedModuleDef *client, PyObject *mod_dict); int (*api_parse_args)(PyObject **parseErrp, PyObject *sipArgs, const char *fmt, ...); int (*api_parse_pair)(PyObject **parseErrp, PyObject *arg0, PyObject *arg1, const char *fmt, ...); void (*api_no_function)(PyObject *parseErr, const char *func, const char *doc); void (*api_no_method)(PyObject *parseErr, const char *scope, const char *method, const char *doc); void (*api_abstract_method)(const char *classname, const char *method); void (*api_bad_class)(const char *classname); void *(*api_get_cpp_ptr)(sipSimpleWrapper *w, const sipTypeDef *td); void *(*api_get_complex_cpp_ptr)(sipSimpleWrapper *w); PyObject *(*api_is_py_method)(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper *sipSelf, const char *cname, const char *mname); void (*api_call_hook)(const char *hookname); void (*api_end_thread)(void); void (*api_raise_unknown_exception)(void); void (*api_raise_type_exception)(const sipTypeDef *td, void *ptr); int (*api_add_type_instance)(PyObject *dict, const char *name, void *cppPtr, const sipTypeDef *td); void (*api_bad_operator_arg)(PyObject *self, PyObject *arg, sipPySlotType st); PyObject *(*api_pyslot_extend)(sipExportedModuleDef *mod, sipPySlotType st, const sipTypeDef *type, PyObject *arg0, PyObject *arg1); void (*api_add_delayed_dtor)(sipSimpleWrapper *w); char (*api_bytes_as_char)(PyObject *obj); const char *(*api_bytes_as_string)(PyObject *obj); char (*api_string_as_ascii_char)(PyObject *obj); const char *(*api_string_as_ascii_string)(PyObject **obj); char (*api_string_as_latin1_char)(PyObject *obj); const char *(*api_string_as_latin1_string)(PyObject **obj); char (*api_string_as_utf8_char)(PyObject *obj); const char *(*api_string_as_utf8_string)(PyObject **obj); #if defined(HAVE_WCHAR_H) wchar_t (*api_unicode_as_wchar)(PyObject *obj); wchar_t *(*api_unicode_as_wstring)(PyObject *obj); #else int (*api_unicode_as_wchar)(PyObject *obj); int *(*api_unicode_as_wstring)(PyObject *obj); #endif int (*api_deprecated)(const char *classname, const char *method); void (*api_keep_reference)(PyObject *self, int key, PyObject *obj); int (*api_parse_kwd_args)(PyObject **parseErrp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, ...); void (*api_add_exception)(sipErrorState es, PyObject **parseErrp); int (*api_parse_result_ex)(sip_gilstate_t, sipVirtErrorHandlerFunc, sipSimpleWrapper *, PyObject *method, PyObject *res, const char *fmt, ...); void (*api_call_error_handler)(sipVirtErrorHandlerFunc, sipSimpleWrapper *, sip_gilstate_t); int (*api_init_mixin)(PyObject *self, PyObject *args, PyObject *kwds, const sipClassTypeDef *ctd); PyObject *(*api_get_reference)(PyObject *self, int key); int (*api_is_derived_class)(sipSimpleWrapper *); void (*api_instance_destroyed_ex)(sipSimpleWrapper **sipSelfp); PyObject *(*api_is_py_method_12_8)(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper **sipSelfp, const char *cname, const char *mname); sipExceptionHandler (*api_next_exception_handler)(void **statep); void (*unused_private_2)(void); void (*unused_private_3)(void); void (*unused_private_4)(void); void (*unused_private_5)(void); } sipAPIDef; const sipAPIDef *sip_init_library(PyObject *mod_dict); /* * These are flags that can be passed to sipCanConvertToType(), * sipConvertToType() and sipForceConvertToType(). */ #define SIP_NOT_NONE 0x01 /* Disallow None. */ #define SIP_NO_CONVERTORS 0x02 /* Disable any type convertors. */ /* * These are flags that can be passed to sipConvertToArray(). These are held * in sw_flags. */ #define SIP_READ_ONLY 0x01 /* The array is read-only. */ #define SIP_OWNS_MEMORY 0x02 /* The array owns its memory. */ /* * These are the state flags returned by %ConvertToTypeCode. Note that the * values share the same "flagspace" as the contents of sw_flags. */ #define SIP_TEMPORARY 0x0001 /* A temporary instance. */ #define SIP_DERIVED_CLASS 0x0002 /* The instance is derived. */ #define SIP_USER 0x0004 /* For use by the user. */ #define SIP_RESERVED 0x0008 /* Reserved for future use by this ABI version. */ /* * These flags are specific to the Qt support API. */ #define SIP_SINGLE_SHOT 0x0001 /* The connection is single shot. */ /* * Useful macros, not part of the public API. */ /* These are held in sw_flags. */ #define SIP_INDIRECT 0x0010 /* If there is a level of indirection. */ #define SIP_ACCFUNC 0x0020 /* If there is an access function. */ #define SIP_NOT_IN_MAP 0x0040 /* If Python object is not in the map. */ #if !defined(Py_LIMITED_API) #define SIP_PY_OWNED 0x0080 /* If owned by Python. */ #define SIP_SHARE_MAP 0x0100 /* If the map slot might be occupied. */ #define SIP_CPP_HAS_REF 0x0200 /* If C/C++ has a reference. */ #define SIP_POSSIBLE_PROXY 0x0400 /* If there might be a proxy slot. */ #define SIP_ALIAS 0x0800 /* If it is an alias. */ #define SIP_CREATED 0x1000 /* If the C/C++ object has been created. */ #define sipIsDerived(sw) ((sw)->sw_flags & SIP_DERIVED_CLASS) #define sipIsIndirect(sw) ((sw)->sw_flags & SIP_INDIRECT) #define sipIsAccessFunc(sw) ((sw)->sw_flags & SIP_ACCFUNC) #define sipNotInMap(sw) ((sw)->sw_flags & SIP_NOT_IN_MAP) #define sipSetNotInMap(sw) ((sw)->sw_flags |= SIP_NOT_IN_MAP) #define sipIsPyOwned(sw) ((sw)->sw_flags & SIP_PY_OWNED) #define sipSetPyOwned(sw) ((sw)->sw_flags |= SIP_PY_OWNED) #define sipResetPyOwned(sw) ((sw)->sw_flags &= ~SIP_PY_OWNED) #define sipCppHasRef(sw) ((sw)->sw_flags & SIP_CPP_HAS_REF) #define sipSetCppHasRef(sw) ((sw)->sw_flags |= SIP_CPP_HAS_REF) #define sipResetCppHasRef(sw) ((sw)->sw_flags &= ~SIP_CPP_HAS_REF) #define sipPossibleProxy(sw) ((sw)->sw_flags & SIP_POSSIBLE_PROXY) #define sipSetPossibleProxy(sw) ((sw)->sw_flags |= SIP_POSSIBLE_PROXY) #define sipIsAlias(sw) ((sw)->sw_flags & SIP_ALIAS) #define sipWasCreated(sw) ((sw)->sw_flags & SIP_CREATED) #endif #define SIP_TYPE_TYPE_MASK 0x0003 /* The type type mask. */ #define SIP_TYPE_CLASS 0x0000 /* If the type is a C++ class. */ #define SIP_TYPE_NAMESPACE 0x0001 /* If the type is a C++ namespace. */ #define SIP_TYPE_MAPPED 0x0002 /* If the type is a mapped type. */ #define SIP_TYPE_ENUM 0x0003 /* If the type is an enum. */ #define SIP_TYPE_USER_STATE 0x0004 /* If the convertors need user state. */ #define SIP_TYPE_ABSTRACT 0x0008 /* If the type is abstract. */ #define SIP_TYPE_SCC 0x0010 /* If the type is subject to sub-class convertors. */ #define SIP_TYPE_ALLOW_NONE 0x0020 /* If the type can handle None. */ #define SIP_TYPE_STUB 0x0040 /* If the type is a stub. */ #define SIP_TYPE_NONLAZY 0x0080 /* If the type has a non-lazy method. */ #define SIP_TYPE_SUPER_INIT 0x0100 /* If the instance's super init should be called. */ #define SIP_TYPE_LIMITED_API 0x0200 /* Use the limited API. If this is more generally required it may need to be moved to the module definition. */ /* The Python base types of enums. */ #define SIP_ENUM_ENUM 0 /* The base type is Enum. */ #define SIP_ENUM_FLAG 1 /* The base type is Flag. */ #define SIP_ENUM_INT_ENUM 2 /* The base type is IntEnum. */ #define SIP_ENUM_INT_FLAG 3 /* The base type is IntFlag. */ #define SIP_ENUM_UINT_ENUM 4 /* The base type is IntEnum with unsigned members. */ /* * The following are part of the public API. */ #define sipTypeIsClass(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_CLASS) #define sipTypeIsNamespace(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_NAMESPACE) #define sipTypeIsMapped(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_MAPPED) #define sipTypeIsEnum(td) (((td)->td_flags & SIP_TYPE_TYPE_MASK) == SIP_TYPE_ENUM) #define sipTypeAsPyTypeObject(td) ((td)->td_py_type) #define sipTypeName(td) sipNameFromPool((td)->td_module, (td)->td_cname) #define sipTypePluginData(td) ((td)->td_plugin_data) /* * The following are not part of the public API. */ #define sipTypeNeedsUserState(td) ((td)->td_flags & SIP_TYPE_USER_STATE) #define sipTypeIsAbstract(td) ((td)->td_flags & SIP_TYPE_ABSTRACT) #define sipTypeHasSCC(td) ((td)->td_flags & SIP_TYPE_SCC) #define sipTypeAllowNone(td) ((td)->td_flags & SIP_TYPE_ALLOW_NONE) #define sipTypeIsStub(td) ((td)->td_flags & SIP_TYPE_STUB) #define sipTypeSetStub(td) ((td)->td_flags |= SIP_TYPE_STUB) #define sipTypeHasNonlazyMethod(td) ((td)->td_flags & SIP_TYPE_NONLAZY) #define sipTypeCallSuperInit(td) ((td)->td_flags & SIP_TYPE_SUPER_INIT) #define sipTypeUseLimitedAPI(td) ((td)->td_flags & SIP_TYPE_LIMITED_API) /* * Get various names from the string pool for various data types. */ #define sipNameFromPool(em, mr) (&((em)->em_strings)[(mr)]) #define sipNameOfModule(em) sipNameFromPool((em), (em)->em_name) #define sipPyNameOfContainer(cod, td) sipNameFromPool((td)->td_module, (cod)->cod_name) #define sipPyNameOfEnum(etd) sipNameFromPool((etd)->etd_base.td_module, (etd)->etd_name) /* * The following are PyQt-specific extensions. These may be removed in SIP v7. * Note that, at the moment, the PyQt5 and PyQt6 extensions are identical. */ /* * The description of a Qt signal for PyQt5. */ typedef int (*pyqt5EmitFunc)(void *, PyObject *); typedef struct _pyqt5QtSignal { /* The normalised C++ name and signature of the signal. */ const char *signature; /* The optional docstring. */ const char *docstring; /* * If the signal is an overload of regular methods then this points to the * code that implements those methods. */ PyMethodDef *non_signals; /* * If the signal has optional arguments then this function will implement * emit() for the signal. */ pyqt5EmitFunc emitter; } pyqt5QtSignal; /* * This is the PyQt5-specific extension to the generated class type structure. */ typedef struct _pyqt5ClassPluginDef { /* A pointer to the QObject sub-class's staticMetaObject class variable. */ const void *static_metaobject; /* * A set of flags. At the moment only bit 0 is used to say if the type is * derived from QFlags. */ unsigned flags; /* * The table of signals emitted by the type. These are grouped by signal * name. */ const pyqt5QtSignal *qt_signals; /* The name of the interface that the class defines. */ const char *qt_interface; } pyqt5ClassPluginDef; /* * The description of a Qt signal for PyQt6. */ typedef int (*pyqt6EmitFunc)(void *, PyObject *); typedef struct _pyqt6QtSignal { /* The normalised C++ name and signature of the signal. */ const char *signature; /* The optional docstring. */ const char *docstring; /* * If the signal is an overload of regular methods then this points to the * code that implements those methods. */ PyMethodDef *non_signals; /* * If the signal has optional arguments then this function will implement * emit() for the signal. */ pyqt6EmitFunc emitter; } pyqt6QtSignal; /* * This is the PyQt6-specific extension to the generated class type structure. */ typedef struct _pyqt6ClassPluginDef { /* A pointer to the QObject sub-class's staticMetaObject class variable. */ const void *static_metaobject; /* * The table of signals emitted by the type. These are grouped by signal * name. */ const pyqt6QtSignal *qt_signals; /* The name of the interface that the class defines. */ const char *qt_interface; } pyqt6ClassPluginDef; /* * This is the PyQt6-specific extension to the generated mapped type structure. */ typedef struct _pyqt6MappedTypePluginDef { /* * A set of flags. At the moment only bit 0 is used to say if the type is * mapped to/from QFlags. */ unsigned flags; } pyqt6MappedTypePluginDef; #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/sipint.h0000644000076500000240000001145100000000000013735 0ustar00philstaff/* * This file defines the SIP library internal interfaces. * * Copyright (c) 2020 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _SIPINT_H #define _SIPINT_H #include #include "sip.h" #ifdef __cplusplus extern "C" { #endif #undef TRUE #define TRUE 1 #undef FALSE #define FALSE 0 /* * This defines a single entry in an object map's hash table. */ typedef struct { void *key; /* The C/C++ address. */ sipSimpleWrapper *first; /* The first object at this address. */ } sipHashEntry; /* * This defines the interface to a hash table class for mapping C/C++ addresses * to the corresponding wrapped Python object. */ typedef struct { int primeIdx; /* Index into table sizes. */ unsigned long size; /* Size of hash table. */ unsigned long unused; /* Nr. unused in hash table. */ unsigned long stale; /* Nr. stale in hash table. */ sipHashEntry *hash_array; /* Current hash table. */ } sipObjectMap; /* * Support for the descriptors. */ extern PyTypeObject sipMethodDescr_Type; PyObject *sipMethodDescr_New(PyMethodDef *pmd); PyObject *sipMethodDescr_Copy(PyObject *orig, PyObject *mixin_name); extern PyTypeObject sipVariableDescr_Type; PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td, const sipContainerDef *cod); PyObject *sipVariableDescr_Copy(PyObject *orig, PyObject *mixin_name); /* * Support for void pointers. */ extern PyTypeObject sipVoidPtr_Type; void *sip_api_convert_to_void_ptr(PyObject *obj); PyObject *sip_api_convert_from_void_ptr(void *val); PyObject *sip_api_convert_from_const_void_ptr(const void *val); PyObject *sip_api_convert_from_void_ptr_and_size(void *val, Py_ssize_t size); PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val, Py_ssize_t size); /* * Support for int convertors. */ int sip_api_convert_to_bool(PyObject *o); char sip_api_long_as_char(PyObject *o); signed char sip_api_long_as_signed_char(PyObject *o); unsigned char sip_api_long_as_unsigned_char(PyObject *o); short sip_api_long_as_short(PyObject *o); unsigned short sip_api_long_as_unsigned_short(PyObject *o); int sip_api_long_as_int(PyObject *o); unsigned int sip_api_long_as_unsigned_int(PyObject *o); long sip_api_long_as_long(PyObject *o); unsigned long sip_api_long_as_unsigned_long(PyObject *o); long long sip_api_long_as_long_long(PyObject *o); unsigned long long sip_api_long_as_unsigned_long_long(PyObject *o); size_t sip_api_long_as_size_t(PyObject *o); extern sipWrapperType sipSimpleWrapper_Type; /* The simple wrapper type. */ /* * These are part of the SIP API but are also used within the SIP module. */ void *sip_api_malloc(size_t nbytes); void sip_api_free(void *mem); void *sip_api_get_address(sipSimpleWrapper *w); void *sip_api_get_cpp_ptr(sipSimpleWrapper *w, const sipTypeDef *td); PyObject *sip_api_convert_from_type(void *cppPtr, const sipTypeDef *td, PyObject *transferObj); void sip_api_instance_destroyed(sipSimpleWrapper *sipSelf); void sip_api_end_thread(void); void *sip_api_force_convert_to_type_us(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp); int sip_api_convert_from_slice_object(PyObject *slice, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength); int sip_api_deprecated(const char *classname, const char *method); /* * These are not part of the SIP API but are used within the SIP module. */ sipClassTypeDef *sipGetGeneratedClassType(const sipEncodedTypeDef *enc, const sipClassTypeDef *ctd); int sipGetPending(void **pp, sipWrapper **op, int *fp); int sipIsPending(void); PyObject *sipWrapInstance(void *cpp, PyTypeObject *py_type, PyObject *args, sipWrapper *owner, int flags); void sipOMInit(sipObjectMap *om); void sipOMFinalise(sipObjectMap *om); sipSimpleWrapper *sipOMFindObject(sipObjectMap *om, void *key, const sipTypeDef *td); void sipOMAddObject(sipObjectMap *om, sipSimpleWrapper *val); int sipOMRemoveObject(sipObjectMap *om, sipSimpleWrapper *val); #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define sipSetBool(p, v) (*(_Bool *)(p) = (v)) #endif #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/siplib.c0000644000076500000240000115512300000000000013712 0ustar00philstaff/* * SIP library code. * * Copyright (c) 2021 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include "sip.h" #include "sipint.h" #include "array.h" /* There doesn't seem to be a standard way of checking for C99 support. */ #if !defined(va_copy) #define va_copy(d, s) ((d) = (s)) #endif /* * The Python metatype for a C++ wrapper type. We inherit everything from the * standard Python metatype except the init and getattro methods and the size * of the type object created is increased to accomodate the extra information * we associate with a wrapped type. */ static PyObject *sipWrapperType_alloc(PyTypeObject *self, Py_ssize_t nitems); static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name); static int sipWrapperType_init(sipWrapperType *self, PyObject *args, PyObject *kwds); static int sipWrapperType_setattro(PyObject *self, PyObject *name, PyObject *value); static PyTypeObject sipWrapperType_Type = { PyVarObject_HEAD_INIT(NULL, 0) _SIP_MODULE_FQ_NAME ".wrappertype", /* tp_name */ sizeof (sipWrapperType), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ sipWrapperType_getattro, /* tp_getattro */ sipWrapperType_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)sipWrapperType_init, /* tp_init */ sipWrapperType_alloc, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }; /* * The Python type that is the super-type for all C++ wrapper types that * support parent/child relationships. */ static int sipWrapper_clear(sipWrapper *self); static void sipWrapper_dealloc(sipWrapper *self); static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg); static sipWrapperType sipWrapper_Type = { #if !defined(STACKLESS) { #endif { PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0) _SIP_MODULE_FQ_NAME ".wrapper", /* tp_name */ sizeof (sipWrapper), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)sipWrapper_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)sipWrapper_traverse, /* tp_traverse */ (inquiry)sipWrapper_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }, { 0, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ }, { 0, /* nb_add */ 0, /* nb_subtract */ 0, /* nb_multiply */ 0, /* nb_remainder */ 0, /* nb_divmod */ 0, /* nb_power */ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ 0, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ 0, /* nb_int */ 0, /* nb_reserved */ 0, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ 0, /* nb_floor_divide */ 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ 0, /* nb_matrix_multiply */ 0, /* nb_inplace_matrix_multiply */ }, { 0, /* mp_length */ 0, /* mp_subscript */ 0, /* mp_ass_subscript */ }, { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* was_sq_slice */ 0, /* sq_ass_item */ 0, /* was_sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }, { 0, /* bf_getbuffer */ 0, /* bf_releasebuffer */ }, 0, /* ht_name */ 0, /* ht_slots */ 0, /* ht_qualname */ 0, /* ht_cached_keys */ #if PY_VERSION_HEX >= 0x03090000 0, /* ht_module */ #endif #if !defined(STACKLESS) }, #endif 0, /* wt_user_type */ 0, /* wt_dict_complete */ 0, /* wt_unused */ 0, /* wt_td */ 0, /* wt_iextend */ 0, /* wt_user_data */ }; static void sip_api_bad_catcher_result(PyObject *method); static void sip_api_bad_length_for_slice(Py_ssize_t seqlen, Py_ssize_t slicelen); static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...); static PyObject *sip_api_call_method(int *isErr, PyObject *method, const char *fmt, ...); static void sip_api_call_procedure_method(sip_gilstate_t gil_state, sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, PyObject *method, const char *fmt, ...); static Py_ssize_t sip_api_convert_from_sequence_index(Py_ssize_t idx, Py_ssize_t len); static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td, int flags); static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp); static void *sip_api_convert_to_type_us(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp); static void *sip_api_force_convert_to_type(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp); static int sip_api_convert_to_enum(PyObject *pyObj, const sipTypeDef *td); static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state); static void sip_api_release_type_us(void *cpp, const sipTypeDef *td, int state, void *user_state); static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td, PyObject *transferObj); static PyObject *sip_api_convert_from_new_pytype(void *cpp, PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...); static int sip_api_get_state(PyObject *transferObj); static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td); static int sip_api_parse_result_ex(sip_gilstate_t gil_state, sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, PyObject *method, PyObject *res, const char *fmt, ...); static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res, const char *fmt, ...); static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, sip_gilstate_t gil_state); static void sip_api_trace(unsigned mask,const char *fmt,...); static void sip_api_transfer_back(PyObject *self); static void sip_api_transfer_to(PyObject *self, PyObject *owner); static int sip_api_export_module(sipExportedModuleDef *client, unsigned api_major, unsigned api_minor, void *unused); static int sip_api_init_module(sipExportedModuleDef *client, PyObject *mod_dict); static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs, const char *fmt, ...); static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, ...); static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0, PyObject *sipArg1, const char *fmt, ...); static void sip_api_no_function(PyObject *parseErr, const char *func, const char *doc); static void sip_api_no_method(PyObject *parseErr, const char *scope, const char *method, const char *doc); static void sip_api_abstract_method(const char *classname, const char *method); static void sip_api_bad_class(const char *classname); static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw); static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper *sipSelf, const char *cname, const char *mname); static PyObject *sip_api_is_py_method_12_8(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper **sipSelfp, const char *cname, const char *mname); static void sip_api_call_hook(const char *hookname); static void sip_api_raise_unknown_exception(void); static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr); static int sip_api_add_type_instance(PyObject *dict, const char *name, void *cppPtr, const sipTypeDef *td); static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg); static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg, sipPySlotType st); static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod, sipPySlotType st, const sipTypeDef *td, PyObject *arg0, PyObject *arg1); static void sip_api_add_delayed_dtor(sipSimpleWrapper *w); static int sip_api_export_symbol(const char *name, void *sym); static void *sip_api_import_symbol(const char *name); static const sipTypeDef *sip_api_find_type(const char *type); static char sip_api_bytes_as_char(PyObject *obj); static const char *sip_api_bytes_as_string(PyObject *obj); static char sip_api_string_as_ascii_char(PyObject *obj); static const char *sip_api_string_as_ascii_string(PyObject **obj); static char sip_api_string_as_latin1_char(PyObject *obj); static const char *sip_api_string_as_latin1_string(PyObject **obj); static char sip_api_string_as_utf8_char(PyObject *obj); static const char *sip_api_string_as_utf8_string(PyObject **obj); #if defined(HAVE_WCHAR_H) static wchar_t sip_api_unicode_as_wchar(PyObject *obj); static wchar_t *sip_api_unicode_as_wstring(PyObject *obj); #else static int sip_api_unicode_as_wchar(PyObject *obj); static int *sip_api_unicode_as_wstring(PyObject *obj); #endif static int sip_api_register_py_type(PyTypeObject *supertype); static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td); static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type); static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td); static const char *sip_api_resolve_typedef(const char *name); static int sip_api_register_attribute_getter(const sipTypeDef *td, sipAttrGetterFunc getter); static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj); static PyObject *sip_api_get_reference(PyObject *self, int key); static int sip_api_is_owned_by_python(sipSimpleWrapper *sw); static int sip_api_is_derived_class(sipSimpleWrapper *sw); static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp); static int sip_api_enable_autoconversion(const sipTypeDef *td, int enable); static int sip_api_init_mixin(PyObject *self, PyObject *args, PyObject *kwds, const sipClassTypeDef *ctd); static void *sip_api_get_mixin_address(sipSimpleWrapper *w, const sipTypeDef *td); static int sip_api_register_proxy_resolver(const sipTypeDef *td, sipProxyResolverFunc resolver); static PyInterpreterState *sip_api_get_interpreter(void); static void sip_api_set_type_user_data(sipWrapperType *wt, void *data); static void *sip_api_get_type_user_data(const sipWrapperType *wt); static PyObject *sip_api_py_type_dict(const PyTypeObject *py_type); static const char *sip_api_py_type_name(const PyTypeObject *py_type); static int sip_api_get_method(PyObject *obj, sipMethodDef *method); static PyObject *sip_api_from_method(const sipMethodDef *method); static int sip_api_get_c_function(PyObject *obj, sipCFunctionDef *c_function); static int sip_api_get_date(PyObject *obj, sipDateDef *date); static PyObject *sip_api_from_date(const sipDateDef *date); static int sip_api_get_datetime(PyObject *obj, sipDateDef *date, sipTimeDef *time); static PyObject *sip_api_from_datetime(const sipDateDef *date, const sipTimeDef *time); static int sip_api_get_time(PyObject *obj, sipTimeDef *time); static PyObject *sip_api_from_time(const sipTimeDef *time); static int sip_api_is_user_type(const sipWrapperType *wt); static int sip_api_check_plugin_for_type(const sipTypeDef *td, const char *name); static PyObject *sip_api_unicode_new(Py_ssize_t len, unsigned maxchar, int *kind, void **data); static void sip_api_unicode_write(int kind, void *data, int index, unsigned value); static void *sip_api_unicode_data(PyObject *obj, int *char_size, Py_ssize_t *len); static int sip_api_get_buffer_info(PyObject *obj, sipBufferInfoDef *bi); static void sip_api_release_buffer_info(sipBufferInfoDef *bi); static PyObject *sip_api_get_user_object(const sipSimpleWrapper *sw); static void sip_api_set_user_object(sipSimpleWrapper *sw, PyObject *user); static int sip_api_enable_gc(int enable); static void sip_api_print_object(PyObject *o); static int sip_api_register_event_handler(sipEventType type, const sipTypeDef *td, void *handler); static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp); static void sip_api_visit_wrappers(sipWrapperVisitorFunc visitor, void *closure); static int sip_api_register_exit_notifier(PyMethodDef *md); static int sip_api_is_enum_flag(PyObject *o); static sipExceptionHandler sip_api_next_exception_handler(void **statep); /* * The data structure that represents the SIP API. */ static const sipAPIDef sip_api = { /* This must be first. */ sip_api_export_module, /* * The following are part of the public API. */ (PyTypeObject *)&sipSimpleWrapper_Type, (PyTypeObject *)&sipWrapper_Type, &sipWrapperType_Type, &sipVoidPtr_Type, sip_api_bad_catcher_result, sip_api_bad_length_for_slice, sip_api_build_result, sip_api_call_method, sip_api_call_procedure_method, sip_api_convert_from_sequence_index, sip_api_can_convert_to_type, sip_api_convert_to_type, sip_api_convert_to_type_us, sip_api_force_convert_to_type, sip_api_force_convert_to_type_us, sip_api_release_type, sip_api_release_type_us, sip_api_convert_from_type, sip_api_convert_from_new_type, sip_api_convert_from_enum, sip_api_get_state, sip_api_free, sip_api_get_pyobject, sip_api_malloc, sip_api_parse_result, sip_api_trace, sip_api_transfer_back, sip_api_transfer_to, sip_api_long_as_unsigned_long, sip_api_convert_from_void_ptr, sip_api_convert_from_const_void_ptr, sip_api_convert_from_void_ptr_and_size, sip_api_convert_from_const_void_ptr_and_size, sip_api_convert_to_void_ptr, sip_api_export_symbol, sip_api_import_symbol, sip_api_find_type, sip_api_register_py_type, sip_api_type_from_py_type_object, sip_api_type_scope, sip_api_resolve_typedef, sip_api_register_attribute_getter, sip_api_bad_callable_arg, sip_api_get_address, sip_api_enable_autoconversion, sip_api_get_mixin_address, sip_api_convert_from_new_pytype, sip_api_convert_to_typed_array, sip_api_convert_to_array, sip_api_register_proxy_resolver, sip_api_get_interpreter, sip_api_set_type_user_data, sip_api_get_type_user_data, sip_api_py_type_dict, sip_api_py_type_name, sip_api_get_method, sip_api_from_method, sip_api_get_c_function, sip_api_get_date, sip_api_from_date, sip_api_get_datetime, sip_api_from_datetime, sip_api_get_time, sip_api_from_time, sip_api_is_user_type, sip_api_check_plugin_for_type, sip_api_unicode_new, sip_api_unicode_write, sip_api_unicode_data, sip_api_get_buffer_info, sip_api_release_buffer_info, sip_api_get_user_object, sip_api_set_user_object, sip_api_instance_destroyed, sip_api_is_owned_by_python, sip_api_enable_gc, sip_api_print_object, sip_api_register_event_handler, sip_api_convert_to_enum, sip_api_convert_to_bool, sip_api_long_as_char, sip_api_long_as_signed_char, sip_api_long_as_unsigned_char, sip_api_long_as_short, sip_api_long_as_unsigned_short, sip_api_long_as_int, sip_api_long_as_unsigned_int, sip_api_long_as_long, sip_api_long_as_long_long, sip_api_long_as_unsigned_long_long, sip_api_convert_from_slice_object, sip_api_long_as_size_t, sip_api_visit_wrappers, sip_api_register_exit_notifier, sip_api_is_enum_flag, NULL, NULL, NULL, NULL, NULL, /* * The following are not part of the public API. */ sip_api_init_module, sip_api_parse_args, sip_api_parse_pair, sip_api_no_function, sip_api_no_method, sip_api_abstract_method, sip_api_bad_class, sip_api_get_cpp_ptr, sip_api_get_complex_cpp_ptr, sip_api_is_py_method, sip_api_call_hook, sip_api_end_thread, sip_api_raise_unknown_exception, sip_api_raise_type_exception, sip_api_add_type_instance, sip_api_bad_operator_arg, sip_api_pyslot_extend, sip_api_add_delayed_dtor, sip_api_bytes_as_char, sip_api_bytes_as_string, sip_api_string_as_ascii_char, sip_api_string_as_ascii_string, sip_api_string_as_latin1_char, sip_api_string_as_latin1_string, sip_api_string_as_utf8_char, sip_api_string_as_utf8_string, sip_api_unicode_as_wchar, sip_api_unicode_as_wstring, sip_api_deprecated, sip_api_keep_reference, sip_api_parse_kwd_args, sip_api_add_exception, sip_api_parse_result_ex, sip_api_call_error_handler, sip_api_init_mixin, sip_api_get_reference, sip_api_is_derived_class, sip_api_instance_destroyed_ex, sip_api_is_py_method_12_8, sip_api_next_exception_handler, NULL, NULL, NULL, NULL, }; #define IS_UNSIGNED_ENUM(etd) ((etd)->etd_base_type == SIP_ENUM_UINT_ENUM || (etd)->etd_base_type == SIP_ENUM_INT_FLAG || (etd)->etd_base_type == SIP_ENUM_FLAG) #define AUTO_DOCSTRING '\1' /* Marks an auto class docstring. */ /* * These are the format flags supported by argument parsers. */ #define FMT_AP_DEREF 0x01 /* The pointer will be dereferenced. */ #define FMT_AP_TRANSFER 0x02 /* Implement /Transfer/. */ #define FMT_AP_TRANSFER_BACK 0x04 /* Implement /TransferBack/. */ #define FMT_AP_NO_CONVERTORS 0x08 /* Suppress any convertors. */ #define FMT_AP_TRANSFER_THIS 0x10 /* Support for /TransferThis/. */ /* * These are the format flags supported by result parsers. Deprecated values * have a _DEPR suffix. */ #define FMT_RP_DEREF 0x01 /* The pointer will be dereferenced. */ #define FMT_RP_FACTORY 0x02 /* /Factory/ or /TransferBack/. */ #define FMT_RP_MAKE_COPY 0x04 /* Return a copy of the value. */ #define FMT_RP_NO_STATE_DEPR 0x04 /* Don't return the C/C++ state. */ /* * The different reasons for failing to parse an overload. These include * internal (i.e. non-user) errors. */ typedef enum { Ok, Unbound, TooFew, TooMany, UnknownKeyword, Duplicate, WrongType, Raised, KeywordNotString, Exception, Overflow } sipParseFailureReason; /* * The description of a failure to parse an overload because of a user error. */ typedef struct _sipParseFailure { sipParseFailureReason reason; /* The reason for the failure. */ const char *detail_str; /* The detail if a string. */ PyObject *detail_obj; /* The detail if a Python object. */ int arg_nr; /* The wrong positional argument. */ const char *arg_name; /* The wrong keyword argument. */ int overflow_arg_nr; /* The overflowed positional argument. */ const char *overflow_arg_name; /* The overflowed keyword argument. */ } sipParseFailure; /* * An entry in a linked list of name/symbol pairs. */ typedef struct _sipSymbol { const char *name; /* The name. */ void *symbol; /* The symbol. */ struct _sipSymbol *next; /* The next in the list. */ } sipSymbol; /* * An entry in a linked list of Python objects. */ typedef struct _sipPyObject { PyObject *object; /* The Python object. */ struct _sipPyObject *next; /* The next in the list. */ } sipPyObject; /* * An entry in the linked list of attribute getters. */ typedef struct _sipAttrGetter { PyTypeObject *type; /* The Python type being handled. */ sipAttrGetterFunc getter; /* The getter. */ struct _sipAttrGetter *next; /* The next in the list. */ } sipAttrGetter; /* * An entry in the linked list of proxy resolvers. */ typedef struct _sipProxyResolver { const sipTypeDef *td; /* The type the resolver handles. */ sipProxyResolverFunc resolver; /* The resolver. */ struct _sipProxyResolver *next; /* The next in the list. */ } sipProxyResolver; /* * An entry in the linked list of event handlers. */ typedef struct _sipEventHandler { const sipClassTypeDef *ctd; /* The type the handler handles. */ void *handler; /* The handler. */ struct _sipEventHandler *next; /* The next in the list. */ } sipEventHandler; /* * Various strings as Python objects created as and when needed. */ static PyObject *licenseName = NULL; static PyObject *licenseeName = NULL; static PyObject *typeName = NULL; static PyObject *timestampName = NULL; static PyObject *signatureName = NULL; static sipObjectMap cppPyMap; /* The C/C++ to Python map. */ static sipExportedModuleDef *moduleList = NULL; /* List of registered modules. */ static unsigned traceMask = 0; /* The current trace mask. */ static sipTypeDef *currentType = NULL; /* The type being created. */ static PyObject **unused_backdoor = NULL; /* For passing dict of unused arguments. */ static PyObject *init_name = NULL; /* '__init__'. */ static PyObject *empty_tuple; /* The empty tuple. */ static PyObject *type_unpickler; /* The type unpickler function. */ static sipSymbol *sipSymbolList = NULL; /* The list of published symbols. */ static sipAttrGetter *sipAttrGetters = NULL; /* The list of attribute getters. */ static sipProxyResolver *proxyResolvers = NULL; /* The list of proxy resolvers. */ static sipPyObject *sipRegisteredPyTypes = NULL; /* Registered Python types. */ static sipPyObject *sipDisabledAutoconversions = NULL; /* Python types whose auto-conversion is disabled. */ static PyInterpreterState *sipInterpreter = NULL; /* The interpreter. */ static sipEventHandler *event_handlers[sipEventNrEvents]; /* The event handler lists. */ static PyObject *enum_type = NULL; /* The enum.Enum type. */ static PyObject *int_enum_type = NULL; /* The enum.IntEnum type. */ static PyObject *flag_type = NULL; /* The enum.Flag type. */ static PyObject *int_flag_type = NULL; /* The enum.IntFlag type. */ static void addClassSlots(sipWrapperType *wt, const sipClassTypeDef *ctd); static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots); static void *findSlot(PyObject *self, sipPySlotType st); static void *findSlotInClass(const sipClassTypeDef *psd, sipPySlotType st); static void *findSlotInSlotList(sipPySlotDef *psd, sipPySlotType st); static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2, sipPySlotType st); static int ssizeobjargprocSlot(PyObject *self, Py_ssize_t arg1, PyObject *arg2, sipPySlotType st); static PyObject *buildObject(PyObject *tup, const char *fmt, va_list va); static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, va_list va_orig); static int parsePass1(PyObject **parseErrp, PyObject **selfp, int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, va_list va); static int parsePass2(PyObject *self, int selfarg, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, const char *fmt, va_list va); static int parseResult(PyObject *method, PyObject *res, sipSimpleWrapper *py_self, const char *fmt, va_list va); static PyObject *signature_FromDocstring(const char *doc, Py_ssize_t line); static PyObject *detail_FromFailure(PyObject *failure_obj); static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td); static int convertFromSequence(PyObject *seq, const sipTypeDef *td, void **array, Py_ssize_t *nr_elem); static PyObject *convertToSequence(void *array, Py_ssize_t nr_elem, const sipTypeDef *td); static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr, PyObject **selfp); static int compareTypedefName(const void *key, const void *el); static int checkPointer(void *ptr, sipSimpleWrapper *sw); static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type, const sipTypeDef *dst_type); static void finalise(void); static PyObject *getDefaultBase(void); static PyObject *getDefaultSimpleBase(void); static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict, sipExportedModuleDef *client); static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td, PyObject *bases, PyObject *metatype, PyObject *mod_dict, PyObject *type_dict, sipExportedModuleDef *client); static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd, PyObject *mod_dict); static int createMappedType(sipExportedModuleDef *client, sipMappedTypeDef *mtd, PyObject *mod_dict); static sipExportedModuleDef *getModule(PyObject *mname_obj); static PyObject *pickle_type(PyObject *obj, PyObject *args); static PyObject *unpickle_type(PyObject *obj, PyObject *args); static int setReduce(PyTypeObject *type, PyMethodDef *pickler); static int createEnum(sipExportedModuleDef *client, sipEnumTypeDef *etd, sipIntInstanceDef **next_int_p, PyObject *dict); static PyObject *createEnumObject(sipExportedModuleDef *client, sipEnumTypeDef *etd, sipIntInstanceDef **next_int_p, PyObject *name); static PyObject *createTypeDict(sipExportedModuleDef *em); static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, sipExportedModuleDef *em); static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr); static int convertPass(const sipTypeDef **tdp, void **cppPtr); static void *getPtrTypeDef(sipSimpleWrapper *self, const sipClassTypeDef **ctd); static int addInstances(PyObject *dict, sipInstancesDef *id); static int addVoidPtrInstances(PyObject *dict, sipVoidPtrInstanceDef *vi); static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci); static int addStringInstances(PyObject *dict, sipStringInstanceDef *si); static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii); static int addLongInstances(PyObject *dict, sipLongInstanceDef *li); static int addUnsignedLongInstances(PyObject *dict, sipUnsignedLongInstanceDef *uli); static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli); static int addUnsignedLongLongInstances(PyObject *dict, sipUnsignedLongLongInstanceDef *ulli); static int addDoubleInstances(PyObject *dict, sipDoubleInstanceDef *di); static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti); static int addSingleTypeInstance(PyObject *dict, const char *name, void *cppPtr, const sipTypeDef *td, int initflags); static int addLicense(PyObject *dict, sipLicenseDef *lc); static PyObject *assign(PyObject *self, PyObject *args); static PyObject *cast(PyObject *self, PyObject *args); static PyObject *callDtor(PyObject *self, PyObject *args); static PyObject *dumpWrapper(PyObject *self, PyObject *arg); static PyObject *enableAutoconversion(PyObject *self, PyObject *args); static PyObject *isDeleted(PyObject *self, PyObject *args); static PyObject *isPyCreated(PyObject *self, PyObject *args); static PyObject *isPyOwned(PyObject *self, PyObject *args); static PyObject *setDeleted(PyObject *self, PyObject *args); static PyObject *setTraceMask(PyObject *self, PyObject *args); static PyObject *wrapInstance(PyObject *self, PyObject *args); static PyObject *unwrapInstance(PyObject *self, PyObject *args); static PyObject *transferBack(PyObject *self, PyObject *args); static PyObject *transferTo(PyObject *self, PyObject *args); static void clear_wrapper(sipSimpleWrapper *sw); static void print_object(const char *label, PyObject *obj); static void addToParent(sipWrapper *self, sipWrapper *owner); static void removeFromParent(sipWrapper *self); static void detachChildren(sipWrapper *self); static void release(void *addr, const sipTypeDef *td, int state, void *user_state); static void callPyDtor(sipSimpleWrapper *self); static int parseBytes_AsCharArray(PyObject *obj, const char **ap, Py_ssize_t *aszp); static int parseBytes_AsChar(PyObject *obj, char *ap); static int parseBytes_AsString(PyObject *obj, const char **ap); static int parseString_AsASCIIChar(PyObject *obj, char *ap); static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap); static int parseString_AsLatin1Char(PyObject *obj, char *ap); static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap); static int parseString_AsUTF8Char(PyObject *obj, char *ap); static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap); static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap); static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj, const char **ap); #if defined(HAVE_WCHAR_H) static int parseWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp); static int convertToWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp); static int parseWChar(PyObject *obj, wchar_t *ap); static int convertToWChar(PyObject *obj, wchar_t *ap); static int parseWCharString(PyObject *obj, wchar_t **ap); static int convertToWCharString(PyObject *obj, wchar_t **ap); #else static void raiseNoWChar(); #endif static void *getComplexCppPtr(sipSimpleWrapper *w, const sipTypeDef *td); static PyObject *findPyType(const char *name); static int addPyObjectToList(sipPyObject **head, PyObject *object); static PyObject *getDictFromObject(PyObject *obj); static void forgetObject(sipSimpleWrapper *sw); static int add_lazy_container_attrs(const sipTypeDef *td, sipContainerDef *cod, PyObject *dict); static int add_lazy_attrs(const sipTypeDef *td); static int add_all_lazy_attrs(const sipTypeDef *td); static int objectify(const char *s, PyObject **objp); static void add_failure(PyObject **parseErrp, sipParseFailure *failure); static PyObject *bad_type_str(int arg_nr, PyObject *arg); static void *explicit_access_func(sipSimpleWrapper *sw, AccessFuncOp op); static void *indirect_access_func(sipSimpleWrapper *sw, AccessFuncOp op); static void clear_access_func(sipSimpleWrapper *sw); static int check_encoded_string(PyObject *obj); static int isNonlazyMethod(PyMethodDef *pmd); static int addMethod(PyObject *dict, PyMethodDef *pmd); static PyObject *create_property(sipVariableDef *vd); static PyObject *create_function(PyMethodDef *ml); static PyObject *sip_exit(PyObject *self, PyObject *args); static sipConvertFromFunc get_from_convertor(const sipTypeDef *td); static sipPyObject **autoconversion_disabled(const sipTypeDef *td); static void fix_slots(PyTypeObject *py_type, sipPySlotDef *psd); static sipFinalFunc find_finalisation(sipClassTypeDef *ctd); static PyObject *next_in_mro(PyObject *self, PyObject *after); static int super_init(PyObject *self, PyObject *args, PyObject *kwds, PyObject *type); static sipSimpleWrapper *deref_mixin(sipSimpleWrapper *w); static PyObject *wrap_simple_instance(void *cpp, const sipTypeDef *td, sipWrapper *owner, int flags); static void *resolve_proxy(const sipTypeDef *td, void *proxy); static PyObject *call_method(PyObject *method, const char *fmt, va_list va); static int importTypes(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em); static int importErrorHandlers(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em); static int importExceptions(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em); static int is_subtype(const sipClassTypeDef *ctd, const sipClassTypeDef *base_ctd); static PyObject *import_module_attr(const char *module, const char *attr); static const sipContainerDef *get_container(const sipTypeDef *td); static PyObject *get_qualname(const sipTypeDef *td, PyObject *name); static void handle_failed_int_conversion(sipParseFailure *pf, PyObject *arg); static void handle_failed_type_conversion(sipParseFailure *pf, PyObject *arg); static void enum_expected(PyObject *obj, const sipTypeDef *td); static int dict_set_and_discard(PyObject *dict, const char *name, PyObject *obj); static void raise_no_convert_from(const sipTypeDef *td); static void raise_no_convert_to(PyObject *py, const sipTypeDef *td); static int user_state_is_valid(const sipTypeDef *td, void **user_statep); static PyObject *get_enum_type(const sipTypeDef *td); /* * Initialise the module as a library. */ const sipAPIDef *sip_init_library(PyObject *mod_dict) { static PyMethodDef methods[] = { /* The type unpickler must be first. */ {"_unpickle_type", unpickle_type, METH_VARARGS, NULL}, {"assign", assign, METH_VARARGS, NULL}, {"cast", cast, METH_VARARGS, NULL}, {"delete", callDtor, METH_VARARGS, NULL}, {"dump", dumpWrapper, METH_O, NULL}, {"enableautoconversion", enableAutoconversion, METH_VARARGS, NULL}, {"isdeleted", isDeleted, METH_VARARGS, NULL}, {"ispycreated", isPyCreated, METH_VARARGS, NULL}, {"ispyowned", isPyOwned, METH_VARARGS, NULL}, {"setdeleted", setDeleted, METH_VARARGS, NULL}, {"settracemask", setTraceMask, METH_VARARGS, NULL}, {"transferback", transferBack, METH_VARARGS, NULL}, {"transferto", transferTo, METH_VARARGS, NULL}, {"wrapinstance", wrapInstance, METH_VARARGS, NULL}, {"unwrapinstance", unwrapInstance, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; static PyMethodDef sip_exit_md = { "_sip_exit", sip_exit, METH_NOARGS, NULL }; PyObject *obj; PyMethodDef *md; #if PY_VERSION_HEX < 0x03070000 && defined(WITH_THREAD) PyEval_InitThreads(); #endif /* Get the enum types. */ if ((obj = PyImport_ImportModule("enum")) == NULL) return NULL; enum_type = PyObject_GetAttrString(obj, "Enum"); int_enum_type = PyObject_GetAttrString(obj, "IntEnum"); flag_type = PyObject_GetAttrString(obj, "Flag"); int_flag_type = PyObject_GetAttrString(obj, "IntFlag"); Py_DECREF(obj); if (enum_type == NULL || int_enum_type == NULL || flag_type == NULL || int_flag_type == NULL) { Py_XDECREF(enum_type); Py_XDECREF(int_enum_type); Py_XDECREF(flag_type); Py_XDECREF(int_flag_type); return NULL; } /* Add the SIP version number. */ obj = PyLong_FromLong(SIP_VERSION); if (dict_set_and_discard(mod_dict, "SIP_VERSION", obj) < 0) return NULL; obj = PyUnicode_FromString(SIP_VERSION_STR); if (dict_set_and_discard(mod_dict, "SIP_VERSION_STR", obj) < 0) return NULL; /* Add the methods. */ for (md = methods; md->ml_name != NULL; ++md) { PyObject *meth = PyCFunction_New(md, NULL); if (dict_set_and_discard(mod_dict, md->ml_name, meth) < 0) return NULL; if (md == &methods[0]) { Py_INCREF(meth); type_unpickler = meth; } } /* Initialise the types. */ sipWrapperType_Type.tp_base = &PyType_Type; if (PyType_Ready(&sipWrapperType_Type) < 0) return NULL; if (PyType_Ready((PyTypeObject *)&sipSimpleWrapper_Type) < 0) return NULL; if (sip_api_register_py_type((PyTypeObject *)&sipSimpleWrapper_Type) < 0) return NULL; #if defined(STACKLESS) sipWrapper_Type.super.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type; #else sipWrapper_Type.super.ht_type.tp_base = (PyTypeObject *)&sipSimpleWrapper_Type; #endif if (PyType_Ready((PyTypeObject *)&sipWrapper_Type) < 0) return NULL; if (PyType_Ready(&sipMethodDescr_Type) < 0) return NULL; if (PyType_Ready(&sipVariableDescr_Type) < 0) return NULL; if (PyType_Ready(&sipVoidPtr_Type) < 0) return NULL; if (PyType_Ready(&sipArray_Type) < 0) return NULL; /* Add the public types. */ if (PyDict_SetItemString(mod_dict, "wrappertype", (PyObject *)&sipWrapperType_Type) < 0) return NULL; if (PyDict_SetItemString(mod_dict, "simplewrapper", (PyObject *)&sipSimpleWrapper_Type) < 0) return NULL; if (PyDict_SetItemString(mod_dict, "wrapper", (PyObject *)&sipWrapper_Type) < 0) return NULL; if (PyDict_SetItemString(mod_dict, "voidptr", (PyObject *)&sipVoidPtr_Type) < 0) return NULL; /* These will always be needed. */ if (objectify("__init__", &init_name) < 0) return NULL; if ((empty_tuple = PyTuple_New(0)) == NULL) return NULL; /* Initialise the object map. */ sipOMInit(&cppPyMap); /* Make sure we are notified at the end of the exit process. */ if (Py_AtExit(finalise) < 0) return NULL; /* Make sure we are notified at the start of the exit process. */ if (sip_api_register_exit_notifier(&sip_exit_md) < 0) return NULL; /* * Get the current interpreter. This will be shared between all threads. */ sipInterpreter = PyThreadState_Get()->interp; return &sip_api; } /* * Set a dictionary item and discard the reference to the item even if there * was an error. */ static int dict_set_and_discard(PyObject *dict, const char *name, PyObject *obj) { int rc; if (obj == NULL) return -1; rc = PyDict_SetItemString(dict, name, obj); Py_DECREF(obj); return rc; } #if _SIP_MODULE_SHARED /* * The Python module initialisation function. */ #if defined(SIP_STATIC_MODULE) PyObject *_SIP_MODULE_ENTRY(void) #else PyMODINIT_FUNC _SIP_MODULE_ENTRY(void) #endif { static PyModuleDef module_def = { PyModuleDef_HEAD_INIT, _SIP_MODULE_FQ_NAME, /* m_name */ NULL, /* m_doc */ -1, /* m_size */ NULL, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; const sipAPIDef *api; PyObject *mod, *mod_dict, *api_obj; /* Create the module. */ if ((mod = PyModule_Create(&module_def)) == NULL) return NULL; mod_dict = PyModule_GetDict(mod); /* Initialise the module dictionary and static variables. */ if ((api = sip_init_library(mod_dict)) == NULL) return NULL; /* Publish the SIP API. */ api_obj = PyCapsule_New((void *)api, _SIP_MODULE_FQ_NAME "._C_API", NULL); if (dict_set_and_discard(mod_dict, "_C_API", api_obj) < 0) { Py_DECREF(mod); return NULL; } return mod; } #endif /* * Return the current interpreter, if there is one. */ static PyInterpreterState *sip_api_get_interpreter(void) { return sipInterpreter; } /* * Display a printf() style message to stderr according to the current trace * mask. */ static void sip_api_trace(unsigned mask, const char *fmt, ...) { va_list ap; va_start(ap,fmt); if (mask & traceMask) vfprintf(stderr, fmt, ap); va_end(ap); } /* * Set the trace mask. */ static PyObject *setTraceMask(PyObject *self, PyObject *args) { unsigned new_mask; (void)self; if (PyArg_ParseTuple(args, "I:settracemask", &new_mask)) { traceMask = new_mask; Py_INCREF(Py_None); return Py_None; } return NULL; } /* * Dump various bits of potentially useful information to stdout. Note that we * use the same calling convention as sys.getrefcount() so that it has the * same caveat regarding the reference count. */ static PyObject *dumpWrapper(PyObject *self, PyObject *arg) { sipSimpleWrapper *sw; (void)self; if (!PyObject_TypeCheck(arg, (PyTypeObject *)&sipSimpleWrapper_Type)) { PyErr_Format(PyExc_TypeError, "dump() argument 1 must be " _SIP_MODULE_FQ_NAME ".simplewrapper, not %s", Py_TYPE(arg)->tp_name); return NULL; } sw = (sipSimpleWrapper *)arg; print_object(NULL, (PyObject *)sw); printf(" Reference count: %" PY_FORMAT_SIZE_T "d\n", Py_REFCNT(sw)); printf(" Address of wrapped object: %p\n", sip_api_get_address(sw)); printf(" Created by: %s\n", (sipIsDerived(sw) ? "Python" : "C/C++")); printf(" To be destroyed by: %s\n", (sipIsPyOwned(sw) ? "Python" : "C/C++")); if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type)) { sipWrapper *w = (sipWrapper *)sw; print_object("Parent wrapper", (PyObject *)w->parent); print_object("Next sibling wrapper", (PyObject *)w->sibling_next); print_object("Previous sibling wrapper", (PyObject *)w->sibling_prev); print_object("First child wrapper", (PyObject *)w->first_child); } Py_INCREF(Py_None); return Py_None; } /* * Write a reference to a wrapper to stdout. */ static void print_object(const char *label, PyObject *obj) { if (label != NULL) printf(" %s: ", label); if (obj != NULL) PyObject_Print(obj, stdout, 0); else printf("NULL"); printf("\n"); } /* * Transfer the ownership of an instance to C/C++. */ static PyObject *transferTo(PyObject *self, PyObject *args) { PyObject *w, *owner; (void)self; if (PyArg_ParseTuple(args, "O!O:transferto", &sipWrapper_Type, &w, &owner)) { if (owner == Py_None) { /* * Note that the Python API is different to the C API when the * owner is None. */ owner = NULL; } else if (!PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type)) { PyErr_Format(PyExc_TypeError, "transferto() argument 2 must be " _SIP_MODULE_FQ_NAME ".wrapper, not %s", Py_TYPE(owner)->tp_name); return NULL; } sip_api_transfer_to(w, owner); Py_INCREF(Py_None); return Py_None; } return NULL; } /* * Transfer the ownership of an instance to Python. */ static PyObject *transferBack(PyObject *self, PyObject *args) { PyObject *w; (void)self; if (PyArg_ParseTuple(args, "O!:transferback", &sipWrapper_Type, &w)) { sip_api_transfer_back(w); Py_INCREF(Py_None); return Py_None; } return NULL; } /* * Invoke the assignment operator for a C++ instance. */ static PyObject *assign(PyObject *self, PyObject *args) { sipSimpleWrapper *dst, *src; PyTypeObject *dst_type, *src_type; const sipTypeDef *td, *super_td; sipAssignFunc assign_helper; void *dst_addr, *src_addr; (void)self; if (!PyArg_ParseTuple(args, "O!O!:assign", &sipSimpleWrapper_Type, &dst, &sipSimpleWrapper_Type, &src)) return NULL; /* Get the assignment helper. */ dst_type = Py_TYPE(dst); td = ((sipWrapperType *)dst_type)->wt_td; if (sipTypeIsMapped(td)) assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign; else assign_helper = ((const sipClassTypeDef *)td)->ctd_assign; if (assign_helper == NULL) { PyErr_SetString(PyExc_TypeError, "argument 1 of assign() does not support assignment"); return NULL; } /* Check the types are compatible. */ src_type = Py_TYPE(src); if (src_type == dst_type) { super_td = NULL; } else if (PyType_IsSubtype(src_type, dst_type)) { super_td = td; } else { PyErr_SetString(PyExc_TypeError, "type of argument 1 of assign() must be a super-type of type of argument 2"); return NULL; } /* Get the addresses. */ if ((dst_addr = sip_api_get_cpp_ptr(dst, NULL)) == NULL) return NULL; if ((src_addr = sip_api_get_cpp_ptr(src, super_td)) == NULL) return NULL; /* Do the assignment. */ assign_helper(dst_addr, 0, src_addr); Py_INCREF(Py_None); return Py_None; } /* * Cast an instance to one of it's sub or super-classes by returning a new * Python object with the superclass type wrapping the same C++ instance. */ static PyObject *cast(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; sipWrapperType *wt; const sipTypeDef *td; void *addr; PyTypeObject *ft, *tt; (void)self; if (!PyArg_ParseTuple(args, "O!O!:cast", &sipSimpleWrapper_Type, &sw, &sipWrapperType_Type, &wt)) return NULL; ft = Py_TYPE(sw); tt = (PyTypeObject *)wt; if (ft == tt || PyType_IsSubtype(tt, ft)) td = NULL; else if (PyType_IsSubtype(ft, tt)) td = wt->wt_td; else { PyErr_SetString(PyExc_TypeError, "argument 1 of cast() must be an instance of a sub or super-type of argument 2"); return NULL; } if ((addr = sip_api_get_cpp_ptr(sw, td)) == NULL) return NULL; /* * We don't put this new object into the map so that the original object is * always found. It would also totally confuse the map logic. */ return wrap_simple_instance(addr, wt->wt_td, NULL, (sw->sw_flags | SIP_NOT_IN_MAP) & ~SIP_PY_OWNED); } /* * Call an instance's dtor. */ static PyObject *callDtor(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; void *addr; const sipClassTypeDef *ctd; (void)self; if (!PyArg_ParseTuple(args, "O!:delete", &sipSimpleWrapper_Type, &sw)) return NULL; addr = getPtrTypeDef(sw, &ctd); if (checkPointer(addr, sw) < 0) return NULL; clear_wrapper(sw); release(addr, (const sipTypeDef *)ctd, sw->sw_flags, NULL); Py_INCREF(Py_None); return Py_None; } /* * Check if an instance still exists without raising an exception. */ static PyObject *isDeleted(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; PyObject *res; (void)self; if (!PyArg_ParseTuple(args, "O!:isdeleted", &sipSimpleWrapper_Type, &sw)) return NULL; res = (sip_api_get_address(sw) == NULL ? Py_True : Py_False); Py_INCREF(res); return res; } /* * Check if an instance was created by Python. */ static PyObject *isPyCreated(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; PyObject *res; (void)self; if (!PyArg_ParseTuple(args, "O!:ispycreated", &sipSimpleWrapper_Type, &sw)) return NULL; /* sipIsDerived() is a misnomer. */ res = (sipIsDerived(sw) ? Py_True : Py_False); Py_INCREF(res); return res; } /* * Check if an instance is owned by Python or C/C++. */ static PyObject *isPyOwned(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; PyObject *res; (void)self; if (!PyArg_ParseTuple(args, "O!:ispyowned", &sipSimpleWrapper_Type, &sw)) return NULL; res = (sipIsPyOwned(sw) ? Py_True : Py_False); Py_INCREF(res); return res; } /* * Mark an instance as having been deleted. */ static PyObject *setDeleted(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; (void)self; if (!PyArg_ParseTuple(args, "O!:setdeleted", &sipSimpleWrapper_Type, &sw)) return NULL; clear_wrapper(sw); Py_INCREF(Py_None); return Py_None; } /* * Unwrap an instance. */ static PyObject *unwrapInstance(PyObject *self, PyObject *args) { sipSimpleWrapper *sw; (void)self; if (PyArg_ParseTuple(args, "O!:unwrapinstance", &sipSimpleWrapper_Type, &sw)) { void *addr; /* * We just get the pointer but don't try and cast it (which isn't * needed and wouldn't work with the way casts are currently * implemented if we are unwrapping something derived from a wrapped * class). */ if ((addr = sip_api_get_cpp_ptr(sw, NULL)) == NULL) return NULL; return PyLong_FromVoidPtr(addr); } return NULL; } /* * Wrap an instance. */ static PyObject *wrapInstance(PyObject *self, PyObject *args) { unsigned long long addr; sipWrapperType *wt; (void)self; if (PyArg_ParseTuple(args, "KO!:wrapinstance", &addr, &sipWrapperType_Type, &wt)) return sip_api_convert_from_type((void *)addr, wt->wt_td, NULL); return NULL; } /* * Register a client module. A negative value is returned and an exception * raised if there was an error. */ static int sip_api_export_module(sipExportedModuleDef *client, unsigned abi_major, unsigned abi_minor, void *unused) { sipExportedModuleDef *em; const char *full_name = sipNameOfModule(client); (void)unused; /* Check that we can support it. */ if (abi_major != SIP_ABI_MAJOR_VERSION || abi_minor > SIP_ABI_MINOR_VERSION) { #if SIP_ABI_MINOR_VERSION > 0 PyErr_Format(PyExc_RuntimeError, "the sip module implements ABI v%d.0 to v%d.%d but the %s module requires ABI v%d.%d", SIP_ABI_MAJOR_VERSION, SIP_ABI_MAJOR_VERSION, SIP_ABI_MINOR_VERSION, full_name, abi_major, abi_minor); #else PyErr_Format(PyExc_RuntimeError, "the sip module implements ABI v%d.0 but the %s module requires ABI v%d.%d", SIP_ABI_MAJOR_VERSION, full_name, abi_major, abi_minor); #endif return -1; } /* Import any required modules. */ if (client->em_imports != NULL) { sipImportedModuleDef *im = client->em_imports; while (im->im_name != NULL) { PyObject *mod; if ((mod = PyImport_ImportModule(im->im_name)) == NULL) return -1; for (em = moduleList; em != NULL; em = em->em_next) if (strcmp(sipNameOfModule(em), im->im_name) == 0) break; if (em == NULL) { PyErr_Format(PyExc_RuntimeError, "the %s module failed to register with the sip module", im->im_name); return -1; } if (im->im_imported_types != NULL && importTypes(client, im, em) < 0) return -1; if (im->im_imported_veh != NULL && importErrorHandlers(client, im, em) < 0) return -1; if (im->im_imported_exceptions != NULL && importExceptions(client, im, em) < 0) return -1; ++im; } } for (em = moduleList; em != NULL; em = em->em_next) { /* SIP clients must have unique names. */ if (strcmp(sipNameOfModule(em), full_name) == 0) { PyErr_Format(PyExc_RuntimeError, "the sip module has already registered a module called %s", full_name); return -1; } } /* Convert the module name to an object. */ if ((client->em_nameobj = PyUnicode_FromString(full_name)) == NULL) return -1; /* Add it to the list of client modules. */ client->em_next = moduleList; moduleList = client; return 0; } /* * Initialise the contents of a client module. By this time anything that * this depends on should have been initialised. A negative value is returned * and an exception raised if there was an error. */ static int sip_api_init_module(sipExportedModuleDef *client, PyObject *mod_dict) { sipExportedModuleDef *em; sipIntInstanceDef *next_int; int i; /* Create the module's types. */ next_int = client->em_instances.id_int; for (i = 0; i < client->em_nrtypes; ++i) { sipTypeDef *td = client->em_types[i]; /* Skip external classes. */ if (td == NULL) continue; /* Skip if already initialised. */ if (td->td_module != NULL) continue; /* If it is a stub then just set the module so we can get its name. */ if (sipTypeIsStub(td)) { td->td_module = client; continue; } if (sipTypeIsEnum(td)) { sipEnumTypeDef *etd = (sipEnumTypeDef *)td; /* * Set this now to get access to the string pool. Unlike other * types we don't use it to determine if the type has been * initialised. */ td->td_module = client; if (etd->etd_scope < 0 && createEnum(client, etd, &next_int, mod_dict) < 0) return -1; } else if (sipTypeIsMapped(td)) { sipMappedTypeDef *mtd = (sipMappedTypeDef *)td; /* If there is a name then we need a namespace. */ if (mtd->mtd_container.cod_name >= 0) { if (createMappedType(client, mtd, mod_dict) < 0) return -1; } else { td->td_module = client; } } else { sipClassTypeDef *ctd = (sipClassTypeDef *)td; /* See if this is a namespace extender. */ if (ctd->ctd_container.cod_name < 0) { sipTypeDef *real_nspace; sipClassTypeDef **last; ctd->ctd_base.td_module = client; real_nspace = getGeneratedType(&ctd->ctd_container.cod_scope, client); /* Append this type to the real one. */ last = &((sipClassTypeDef *)real_nspace)->ctd_nsextender; while (*last != NULL) last = &(*last)->ctd_nsextender; *last = ctd; /* * Save the real namespace type so that it is the correct scope * for any enums or classes defined in this module. */ client->em_types[i] = real_nspace; } else if (createClassType(client, ctd, mod_dict) < 0) return -1; } } /* Add any ints that aren't name enum members. */ if (next_int != NULL) if (addIntInstances(mod_dict, next_int) < 0) return -1; /* Append any initialiser extenders to the relevant classes. */ if (client->em_initextend != NULL) { sipInitExtenderDef *ie = client->em_initextend; while (ie->ie_extender != NULL) { sipTypeDef *td = getGeneratedType(&ie->ie_class, client); sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td); ie->ie_next = wt->wt_iextend; wt->wt_iextend = ie; ++ie; } } /* Set the base class object for any sub-class convertors. */ if (client->em_convertors != NULL) { sipSubClassConvertorDef *scc = client->em_convertors; while (scc->scc_convertor != NULL) { scc->scc_basetype = getGeneratedType(&scc->scc_base, client); ++scc; } } /* Add any global static instances. */ if (addInstances(mod_dict, &client->em_instances) < 0) return -1; /* Add any license. */ if (client->em_license != NULL && addLicense(mod_dict, client->em_license) < 0) return -1; /* See if the new module satisfies any outstanding external types. */ for (em = moduleList; em != NULL; em = em->em_next) { sipExternalTypeDef *etd; if (em == client || em->em_external == NULL) continue; for (etd = em->em_external; etd->et_nr >= 0; ++etd) { if (etd->et_name == NULL) continue; for (i = 0; i < client->em_nrtypes; ++i) { sipTypeDef *td = client->em_types[i]; if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td)) { const char *pyname = sipPyNameOfContainer( &((sipClassTypeDef *)td)->ctd_container, td); if (strcmp(etd->et_name, pyname) == 0) { em->em_types[etd->et_nr] = td; etd->et_name = NULL; break; } } } } } return 0; } /* * Called by the interpreter to do any final clearing up, just in case the * interpreter will re-start. */ static void finalise(void) { sipExportedModuleDef *em; /* * Mark the Python API as unavailable. This should already have been done, * but just in case... */ sipInterpreter = NULL; /* Handle any delayed dtors. */ for (em = moduleList; em != NULL; em = em->em_next) if (em->em_ddlist != NULL) { em->em_delayeddtors(em->em_ddlist); /* Free the list. */ do { sipDelayedDtor *dd = em->em_ddlist; em->em_ddlist = dd->dd_next; sip_api_free(dd); } while (em->em_ddlist != NULL); } licenseName = NULL; licenseeName = NULL; typeName = NULL; timestampName = NULL; signatureName = NULL; /* Release all memory we've allocated directly. */ sipOMFinalise(&cppPyMap); /* Re-initialise those globals that (might) need it. */ moduleList = NULL; } /* * Register the given Python type. */ static int sip_api_register_py_type(PyTypeObject *type) { return addPyObjectToList(&sipRegisteredPyTypes, (PyObject *)type); } /* * Find the registered type with the given name. Raise an exception if it * couldn't be found. */ static PyObject *findPyType(const char *name) { sipPyObject *po; for (po = sipRegisteredPyTypes; po != NULL; po = po->next) { PyObject *type = po->object; if (strcmp(((PyTypeObject *)type)->tp_name, name) == 0) return type; } PyErr_Format(PyExc_RuntimeError, "%s is not a registered type", name); return NULL; } /* * Add a wrapped C/C++ pointer to the list of delayed dtors. */ static void sip_api_add_delayed_dtor(sipSimpleWrapper *sw) { void *ptr; const sipClassTypeDef *ctd; sipExportedModuleDef *em; if ((ptr = getPtrTypeDef(sw, &ctd)) == NULL) return; /* Find the defining module. */ for (em = moduleList; em != NULL; em = em->em_next) { int i; for (i = 0; i < em->em_nrtypes; ++i) if (em->em_types[i] == (const sipTypeDef *)ctd) { sipDelayedDtor *dd; if ((dd = sip_api_malloc(sizeof (sipDelayedDtor))) == NULL) return; /* Add to the list. */ dd->dd_ptr = ptr; dd->dd_name = sipPyNameOfContainer(&ctd->ctd_container, (sipTypeDef *)ctd); dd->dd_isderived = sipIsDerived(sw); dd->dd_next = em->em_ddlist; em->em_ddlist = dd; return; } } } /* * A wrapper around the Python memory allocater that will raise an exception if * if the allocation fails. */ void *sip_api_malloc(size_t nbytes) { void *mem; if ((mem = PyMem_Malloc(nbytes)) == NULL) PyErr_NoMemory(); return mem; } /* * A wrapper around the Python memory de-allocater. */ void sip_api_free(void *mem) { PyMem_Free(mem); } /* * Extend a Python slot by looking in other modules to see if there is an * extender function that can handle the arguments. */ static PyObject *sip_api_pyslot_extend(sipExportedModuleDef *mod, sipPySlotType st, const sipTypeDef *td, PyObject *arg0, PyObject *arg1) { sipExportedModuleDef *em; /* Go through each module. */ for (em = moduleList; em != NULL; em = em->em_next) { sipPySlotExtenderDef *ex; /* Skip the module that couldn't handle the arguments. */ if (em == mod) continue; /* Skip if the module doesn't have any extenders. */ if (em->em_slotextend == NULL) continue; /* Go through each extender. */ for (ex = em->em_slotextend; ex->pse_func != NULL; ++ex) { PyObject *res; /* Skip if not the right slot type. */ if (ex->pse_type != st) continue; /* Check against the type if one was given. */ if (td != NULL && td != getGeneratedType(&ex->pse_class, NULL)) continue; PyErr_Clear(); res = ((binaryfunc)ex->pse_func)(arg0, arg1); if (res != Py_NotImplemented) return res; } } /* The arguments couldn't handled anywhere. */ PyErr_Clear(); Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } /* * Convert a new C/C++ instance to a Python instance of a specific Python type. */ static PyObject *sip_api_convert_from_new_pytype(void *cpp, PyTypeObject *py_type, sipWrapper *owner, sipSimpleWrapper **selfp, const char *fmt, ...) { PyObject *args, *res; va_list va; va_start(va, fmt); if ((args = PyTuple_New(strlen(fmt))) != NULL && buildObject(args, fmt, va) != NULL) { res = sipWrapInstance(cpp, py_type, args, owner, (selfp != NULL ? SIP_DERIVED_CLASS : 0)); /* Initialise the rest of an instance of a derived class. */ if (selfp != NULL) *selfp = (sipSimpleWrapper *)res; } else { res = NULL; } Py_XDECREF(args); va_end(va); return res; } /* * Call a method and return the result. */ static PyObject *call_method(PyObject *method, const char *fmt, va_list va) { PyObject *args, *res; if ((args = PyTuple_New(strlen(fmt))) == NULL) return NULL; if (buildObject(args, fmt, va) != NULL) res = PyObject_CallObject(method, args); else res = NULL; Py_DECREF(args); return res; } /* * Call the Python re-implementation of a C++ virtual that does not return a * value and handle the result.. */ static void sip_api_call_procedure_method(sip_gilstate_t gil_state, sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, PyObject *method, const char *fmt, ...) { PyObject *res; va_list va; va_start(va, fmt); res = call_method(method, fmt, va); va_end(va); if (res != NULL) { Py_DECREF(res); if (res != Py_None) { sip_api_bad_catcher_result(method); res = NULL; } } Py_DECREF(method); if (res == NULL) sip_api_call_error_handler(error_handler, py_self, gil_state); SIP_RELEASE_GIL(gil_state); } /* * Call the Python re-implementation of a C++ virtual. */ static PyObject *sip_api_call_method(int *isErr, PyObject *method, const char *fmt, ...) { PyObject *res; va_list va; va_start(va, fmt); res = call_method(method, fmt, va); va_end(va); if (res == NULL && isErr != NULL) *isErr = TRUE; return res; } /* * Build a result object based on a format string. */ static PyObject *sip_api_build_result(int *isErr, const char *fmt, ...) { PyObject *res = NULL; int badfmt, tupsz; va_list va; va_start(va,fmt); /* Basic validation of the format string. */ badfmt = FALSE; if (*fmt == '(') { char *ep; if ((ep = strchr(fmt,')')) == NULL || ep[1] != '\0') badfmt = TRUE; else tupsz = (int)(ep - fmt - 1); } else if (strlen(fmt) == 1) tupsz = -1; else badfmt = TRUE; if (badfmt) PyErr_Format(PyExc_SystemError,"sipBuildResult(): invalid format string \"%s\"",fmt); else if (tupsz < 0 || (res = PyTuple_New(tupsz)) != NULL) res = buildObject(res,fmt,va); va_end(va); if (res == NULL && isErr != NULL) *isErr = TRUE; return res; } /* * Get the values off the stack and put them into an object. */ static PyObject *buildObject(PyObject *obj, const char *fmt, va_list va) { char ch, termch; int i; /* * The format string has already been checked that it is properly formed if * it is enclosed in parenthesis. */ if (*fmt == '(') { termch = ')'; ++fmt; } else termch = '\0'; i = 0; while ((ch = *fmt++) != termch) { PyObject *el; switch (ch) { case 'g': { char *s; Py_ssize_t l; s = va_arg(va, char *); l = va_arg(va, Py_ssize_t); if (s != NULL) { el = PyBytes_FromStringAndSize(s, l); } else { Py_INCREF(Py_None); el = Py_None; } } break; case 'G': #if defined(HAVE_WCHAR_H) { wchar_t *s; Py_ssize_t l; s = va_arg(va, wchar_t *); l = va_arg(va, Py_ssize_t); if (s != NULL) el = PyUnicode_FromWideChar(s, l); else { Py_INCREF(Py_None); el = Py_None; } } #else raiseNoWChar(); el = NULL; #endif break; case 'b': el = PyBool_FromLong(va_arg(va,int)); break; case 'c': { char c = va_arg(va, int); el = PyBytes_FromStringAndSize(&c, 1); } break; case 'a': { char c = va_arg(va, int); el = PyUnicode_FromStringAndSize(&c, 1); } break; case 'w': #if defined(HAVE_WCHAR_H) { wchar_t c = va_arg(va, int); el = PyUnicode_FromWideChar(&c, 1); } #else raiseNoWChar(); el = NULL; #endif break; case 'F': { int ev = va_arg(va, int); const sipTypeDef *td = va_arg(va, const sipTypeDef *); el = sip_api_convert_from_enum(ev, td); } break; case 'd': case 'f': el = PyFloat_FromDouble(va_arg(va, double)); break; case 'e': case 'h': case 'i': case 'L': el = PyLong_FromLong(va_arg(va, int)); break; case 'l': el = PyLong_FromLong(va_arg(va, long)); break; case 'm': el = PyLong_FromUnsignedLong(va_arg(va, unsigned long)); break; case 'n': el = PyLong_FromLongLong(va_arg(va, long long)); break; case 'o': el = PyLong_FromUnsignedLongLong(va_arg(va, unsigned long long)); break; case 's': { char *s = va_arg(va, char *); if (s != NULL) { el = PyBytes_FromString(s); } else { Py_INCREF(Py_None); el = Py_None; } } break; case 'A': { char *s = va_arg(va, char *); if (s != NULL) { el = PyUnicode_FromString(s); } else { Py_INCREF(Py_None); el = Py_None; } } break; case 'x': #if defined(HAVE_WCHAR_H) { wchar_t *s = va_arg(va, wchar_t *); if (s != NULL) el = PyUnicode_FromWideChar(s, (Py_ssize_t)wcslen(s)); else { Py_INCREF(Py_None); el = Py_None; } } #else raiseNoWChar(); el = NULL; #endif break; case 't': case 'u': case 'M': el = PyLong_FromUnsignedLong(va_arg(va, unsigned)); break; case '=': el = PyLong_FromUnsignedLong(va_arg(va, size_t)); break; case 'N': { void *p = va_arg(va, void *); const sipTypeDef *td = va_arg(va, const sipTypeDef *); PyObject *xfer = va_arg(va, PyObject *); el = sip_api_convert_from_new_type(p, td, xfer); } break; case 'D': { void *p = va_arg(va, void *); const sipTypeDef *td = va_arg(va, const sipTypeDef *); PyObject *xfer = va_arg(va, PyObject *); el = sip_api_convert_from_type(p, td, xfer); } break; case 'r': { void *p = va_arg(va, void *); Py_ssize_t l = va_arg(va, Py_ssize_t); const sipTypeDef *td = va_arg(va, const sipTypeDef *); el = convertToSequence(p, l, td); } break; case 'R': el = va_arg(va,PyObject *); break; case 'S': el = va_arg(va,PyObject *); Py_INCREF(el); break; case 'V': el = sip_api_convert_from_void_ptr(va_arg(va, void *)); break; case 'z': { const char *name = va_arg(va, const char *); void *p = va_arg(va, void *); if (p == NULL) { el = Py_None; Py_INCREF(el); } else { el = PyCapsule_New(p, name, NULL); } } break; default: PyErr_Format(PyExc_SystemError,"buildObject(): invalid format character '%c'",ch); el = NULL; } if (el == NULL) { Py_XDECREF(obj); return NULL; } if (obj == NULL) return el; PyTuple_SET_ITEM(obj,i,el); ++i; } return obj; } /* * Parse a result object based on a format string. As of v9.0 of the API this * is only ever called by handwritten code. */ static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res, const char *fmt, ...) { int rc; va_list va; va_start(va, fmt); rc = parseResult(method, res, NULL, fmt, va); va_end(va); if (isErr != NULL && rc < 0) *isErr = TRUE; return rc; } /* * Parse a result object based on a format string. */ static int sip_api_parse_result_ex(sip_gilstate_t gil_state, sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, PyObject *method, PyObject *res, const char *fmt, ...) { int rc; if (res != NULL) { va_list va; va_start(va, fmt); rc = parseResult(method, res, deref_mixin(py_self), fmt, va); va_end(va); Py_DECREF(res); } else { rc = -1; } Py_DECREF(method); if (rc < 0) sip_api_call_error_handler(error_handler, py_self, gil_state); SIP_RELEASE_GIL(gil_state); return rc; } /* * Call a virtual error handler. This is called with the GIL and from the * thread that raised the error. */ static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, sipSimpleWrapper *py_self, sip_gilstate_t sipGILState) { if (error_handler != NULL) error_handler(deref_mixin(py_self), sipGILState); else PyErr_Print(); } /* * Do the main work of parsing a result object based on a format string. */ static int parseResult(PyObject *method, PyObject *res, sipSimpleWrapper *py_self, const char *fmt, va_list va) { int tupsz, rc = 0; /* We rely on PyErr_Occurred(). */ PyErr_Clear(); /* Get self if it is provided as an argument. */ if (*fmt == 'S') { py_self = va_arg(va, sipSimpleWrapper *); ++fmt; } /* Basic validation of the format string. */ if (*fmt == '(') { char ch; const char *cp = ++fmt; int sub_format = FALSE; tupsz = 0; while ((ch = *cp++) != ')') { if (ch == '\0') { PyErr_Format(PyExc_SystemError, "sipParseResult(): invalid format string \"%s\"", fmt - 1); rc = -1; break; } if (sub_format) { sub_format = FALSE; } else { ++tupsz; /* Some format characters have a sub-format. */ if (strchr("aAHDC", ch) != NULL) sub_format = TRUE; } } if (rc == 0) if (!PyTuple_Check(res) || PyTuple_GET_SIZE(res) != tupsz) { sip_api_bad_catcher_result(method); rc = -1; } } else tupsz = -1; if (rc == 0) { char ch; int i = 0; while ((ch = *fmt++) != '\0' && ch != ')' && rc == 0) { PyObject *arg; int invalid = FALSE; if (tupsz > 0) { arg = PyTuple_GET_ITEM(res,i); ++i; } else arg = res; switch (ch) { case 'g': { const char **p = va_arg(va, const char **); Py_ssize_t *szp = va_arg(va, Py_ssize_t *); if (parseBytes_AsCharArray(arg, p, szp) < 0) invalid = TRUE; } break; case 'G': #if defined(HAVE_WCHAR_H) { wchar_t **p = va_arg(va, wchar_t **); Py_ssize_t *szp = va_arg(va, Py_ssize_t *); if (parseWCharArray(arg, p, szp) < 0) invalid = TRUE; } #else raiseNoWChar(); invalid = TRUE; #endif break; case 'b': { char *p = va_arg(va, void *); int v = sip_api_convert_to_bool(arg); if (v < 0) invalid = TRUE; else if (p != NULL) sipSetBool(p, v); } break; case 'c': { char *p = va_arg(va, char *); if (parseBytes_AsChar(arg, p) < 0) invalid = TRUE; } break; case 'a': { char *p = va_arg(va, char *); int enc; switch (*fmt++) { case 'A': enc = parseString_AsASCIIChar(arg, p); break; case 'L': enc = parseString_AsLatin1Char(arg, p); break; case '8': enc = parseString_AsUTF8Char(arg, p); break; default: enc = -1; } if (enc < 0) invalid = TRUE; } break; case 'w': #if defined(HAVE_WCHAR_H) { wchar_t *p = va_arg(va, wchar_t *); if (parseWChar(arg, p) < 0) invalid = TRUE; } #else raiseNoWChar(); invalid = TRUE; #endif break; case 'd': { double *p = va_arg(va, double *); double v = PyFloat_AsDouble(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'F': { sipTypeDef *td = va_arg(va, sipTypeDef *); int *p = va_arg(va, int *); int v = sip_api_convert_to_enum(arg, td); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'f': { float *p = va_arg(va, float *); float v = (float)PyFloat_AsDouble(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'L': { signed char *p = va_arg(va, signed char *); signed char v = sip_api_long_as_signed_char(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'M': { unsigned char *p = va_arg(va, unsigned char *); unsigned char v = sip_api_long_as_unsigned_char(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'h': { signed short *p = va_arg(va, signed short *); signed short v = sip_api_long_as_short(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 't': { unsigned short *p = va_arg(va, unsigned short *); unsigned short v = sip_api_long_as_unsigned_short(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'e': { int *p = va_arg(va, int *); int v = sip_api_long_as_int(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'i': { int *p = va_arg(va, int *); int v = sip_api_long_as_int(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'u': { unsigned *p = va_arg(va, unsigned *); unsigned v = sip_api_long_as_unsigned_int(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case '=': { size_t *p = va_arg(va, size_t *); size_t v = sip_api_long_as_size_t(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'l': { long *p = va_arg(va, long *); long v = sip_api_long_as_long(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'm': { unsigned long *p = va_arg(va, unsigned long *); unsigned long v = sip_api_long_as_unsigned_long(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'n': { long long *p = va_arg(va, long long *); long long v = sip_api_long_as_long_long(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'o': { unsigned long long *p = va_arg(va, unsigned long long *); unsigned long long v = sip_api_long_as_unsigned_long_long(arg); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'A': { int key = va_arg(va, int); const char **p = va_arg(va, const char **); PyObject *keep; switch (*fmt++) { case 'A': keep = parseString_AsASCIIString(arg, p); break; case 'L': keep = parseString_AsLatin1String(arg, p); break; case '8': keep = parseString_AsUTF8String(arg, p); break; default: keep = NULL; } if (keep == NULL) invalid = TRUE; else sip_api_keep_reference((PyObject *)py_self, key, keep); } break; case 'B': { int key = va_arg(va, int); const char **p = va_arg(va, const char **); if (parseBytes_AsString(arg, p) < 0) invalid = TRUE; else sip_api_keep_reference((PyObject *)py_self, key, arg); } break; case 'x': #if defined(HAVE_WCHAR_H) { wchar_t **p = va_arg(va, wchar_t **); if (parseWCharString(arg, p) < 0) invalid = TRUE; } #else raiseNoWChar(); invalid = TRUE; #endif break; case 'H': { if (*fmt == '\0') { invalid = TRUE; } else { int flags = *fmt++ - '0'; int iserr = FALSE, state; const sipTypeDef *td; void *cpp, *val, *user_state; td = va_arg(va, const sipTypeDef *); cpp = va_arg(va, void **); val = sip_api_force_convert_to_type_us(arg, td, (flags & FMT_RP_FACTORY ? arg : NULL), (flags & FMT_RP_DEREF ? SIP_NOT_NONE : 0), &state, (flags & FMT_RP_MAKE_COPY ? &user_state : NULL), &iserr); if (iserr) { invalid = TRUE; } else if (flags & FMT_RP_MAKE_COPY) { sipAssignFunc assign_helper; if (sipTypeIsMapped(td)) assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign; else assign_helper = ((const sipClassTypeDef *)td)->ctd_assign; assert(assign_helper != NULL); if (cpp != NULL) assign_helper(cpp, 0, val); sip_api_release_type_us(val, td, state, user_state); } else if (cpp != NULL) { *(void **)cpp = val; } } } break; case 'N': { PyTypeObject *type = va_arg(va, PyTypeObject *); PyObject **p = va_arg(va, PyObject **); if (arg == Py_None || PyObject_TypeCheck(arg, type)) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; case 'O': { PyObject **p = va_arg(va, PyObject **); if (p != NULL) { Py_INCREF(arg); *p = arg; } } break; case 'T': { PyTypeObject *type = va_arg(va, PyTypeObject *); PyObject **p = va_arg(va, PyObject **); if (PyObject_TypeCheck(arg, type)) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; case 'V': { void *v = sip_api_convert_to_void_ptr(arg); void **p = va_arg(va, void **); if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } break; case 'z': { const char *name = va_arg(va, const char *); void **p = va_arg(va, void **); if (arg == Py_None) { if (p != NULL) *p = NULL; } else { #if defined(SIP_USE_CAPSULE) void *v = PyCapsule_GetPointer(arg, name); #else void *v = sip_api_convert_to_void_ptr(arg); (void)name; #endif if (PyErr_Occurred()) invalid = TRUE; else if (p != NULL) *p = v; } } break; case 'Z': if (arg != Py_None) invalid = TRUE; break; case '!': { PyObject **p = va_arg(va, PyObject **); if (PyObject_CheckBuffer(arg)) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; case '$': { PyObject **p = va_arg(va, PyObject **); if (arg == Py_None || PyObject_CheckBuffer(arg)) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; case '&': { PyObject **p = va_arg(va, PyObject **); if (PyObject_IsSubclass(arg, enum_type) == 1) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; case '^': { PyObject **p = va_arg(va, PyObject **); if (arg == Py_None || PyObject_IsSubclass(arg, enum_type) == 1) { if (p != NULL) { Py_INCREF(arg); *p = arg; } } else { invalid = TRUE; } } break; default: PyErr_Format(PyExc_SystemError,"sipParseResult(): invalid format character '%c'",ch); rc = -1; } if (invalid) { sip_api_bad_catcher_result(method); rc = -1; break; } } } return rc; } /* * Parse the arguments to a C/C++ function without any side effects. */ static int sip_api_parse_args(PyObject **parseErrp, PyObject *sipArgs, const char *fmt, ...) { int ok; va_list va; va_start(va, fmt); ok = parseKwdArgs(parseErrp, sipArgs, NULL, NULL, NULL, fmt, va); va_end(va); return ok; } /* * Parse the positional and/or keyword arguments to a C/C++ function without * any side effects. */ static int sip_api_parse_kwd_args(PyObject **parseErrp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, ...) { int ok; va_list va; if (unused != NULL) { /* * Initialise the return of any unused keyword arguments. This is * used by any ctor overload. */ *unused = NULL; } va_start(va, fmt); ok = parseKwdArgs(parseErrp, sipArgs, sipKwdArgs, kwdlist, unused, fmt, va); va_end(va); /* Release any unused arguments if the parse failed. */ if (!ok && unused != NULL) { Py_XDECREF(*unused); } return ok; } /* * Parse the arguments to a C/C++ function without any side effects. */ static int parseKwdArgs(PyObject **parseErrp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, va_list va_orig) { int no_tmp_tuple, ok, selfarg; PyObject *self, *single_arg; va_list va; /* Previous second pass errors stop subsequent parses. */ if (*parseErrp != NULL && !PyList_Check(*parseErrp)) return FALSE; /* * See if we are parsing a single argument. In current versions we are * told explicitly by the first character of the format string. In earlier * versions we guessed (sometimes wrongly). */ if (*fmt == '1') { ++fmt; no_tmp_tuple = FALSE; } else no_tmp_tuple = PyTuple_Check(sipArgs); if (no_tmp_tuple) { Py_INCREF(sipArgs); } else if ((single_arg = PyTuple_New(1)) != NULL) { Py_INCREF(sipArgs); PyTuple_SET_ITEM(single_arg, 0, sipArgs); sipArgs = single_arg; } else { /* Stop all parsing and indicate an exception has been raised. */ Py_XDECREF(*parseErrp); *parseErrp = Py_None; Py_INCREF(Py_None); return FALSE; } /* * The first pass checks all the types and does conversions that are cheap * and have no side effects. */ va_copy(va, va_orig); ok = parsePass1(parseErrp, &self, &selfarg, sipArgs, sipKwdArgs, kwdlist, unused, fmt, va); va_end(va); if (ok) { /* * The second pass does any remaining conversions now that we know we * have the right signature. */ va_copy(va, va_orig); ok = parsePass2(self, selfarg, sipArgs, sipKwdArgs, kwdlist, fmt, va); va_end(va); /* Remove any previous failed parses. */ Py_XDECREF(*parseErrp); if (ok) { *parseErrp = NULL; } else { /* Indicate that an exception has been raised. */ *parseErrp = Py_None; Py_INCREF(Py_None); } } Py_DECREF(sipArgs); return ok; } /* * Return a string as a Python object that describes an argument with an * unexpected type. */ static PyObject *bad_type_str(int arg_nr, PyObject *arg) { return PyUnicode_FromFormat("argument %d has unexpected type '%s'", arg_nr, Py_TYPE(arg)->tp_name); } /* * Adds a failure about an argument with an incorrect type to the current list * of exceptions. */ static sipErrorState sip_api_bad_callable_arg(int arg_nr, PyObject *arg) { PyObject *detail = bad_type_str(arg_nr + 1, arg); if (detail == NULL) return sipErrorFail; PyErr_SetObject(PyExc_TypeError, detail); Py_DECREF(detail); return sipErrorContinue; } /* * Adds the current exception to the current list of exceptions (if it is a * user exception) or replace the current list of exceptions. */ static void sip_api_add_exception(sipErrorState es, PyObject **parseErrp) { assert(*parseErrp == NULL); if (es == sipErrorContinue) { sipParseFailure failure; PyObject *e_type, *e_traceback; /* Get the value of the exception. */ PyErr_Fetch(&e_type, &failure.detail_obj, &e_traceback); Py_XDECREF(e_type); Py_XDECREF(e_traceback); failure.reason = Exception; add_failure(parseErrp, &failure); if (failure.reason == Raised) { Py_XDECREF(failure.detail_obj); es = sipErrorFail; } } if (es == sipErrorFail) { Py_XDECREF(*parseErrp); *parseErrp = Py_None; Py_INCREF(Py_None); } } /* * The dtor for parse failure wrapped in a Python object. */ static void failure_dtor(PyObject *capsule) { sipParseFailure *failure = (sipParseFailure *)PyCapsule_GetPointer(capsule, NULL); Py_XDECREF(failure->detail_obj); sip_api_free(failure); } /* * Add a parse failure to the current list of exceptions. */ static void add_failure(PyObject **parseErrp, sipParseFailure *failure) { sipParseFailure *failure_copy; PyObject *failure_obj; /* Create the list if necessary. */ if (*parseErrp == NULL && (*parseErrp = PyList_New(0)) == NULL) { failure->reason = Raised; return; } /* * Make a copy of the failure, convert it to a Python object and add it to * the list. We do it this way to make it as lightweight as possible. */ if ((failure_copy = sip_api_malloc(sizeof (sipParseFailure))) == NULL) { failure->reason = Raised; return; } *failure_copy = *failure; if ((failure_obj = PyCapsule_New(failure_copy, NULL, failure_dtor)) == NULL) { sip_api_free(failure_copy); failure->reason = Raised; return; } /* Ownership of any detail object is now with the wrapped failure. */ failure->detail_obj = NULL; if (PyList_Append(*parseErrp, failure_obj) < 0) { Py_DECREF(failure_obj); failure->reason = Raised; return; } Py_DECREF(failure_obj); } /* * Parse one or a pair of arguments to a C/C++ function without any side * effects. */ static int sip_api_parse_pair(PyObject **parseErrp, PyObject *sipArg0, PyObject *sipArg1, const char *fmt, ...) { int ok, selfarg; PyObject *self, *args; va_list va; /* Previous second pass errors stop subsequent parses. */ if (*parseErrp != NULL && !PyList_Check(*parseErrp)) return FALSE; if ((args = PyTuple_New(sipArg1 != NULL ? 2 : 1)) == NULL) { /* Stop all parsing and indicate an exception has been raised. */ Py_XDECREF(*parseErrp); *parseErrp = Py_None; Py_INCREF(Py_None); return FALSE; } Py_INCREF(sipArg0); PyTuple_SET_ITEM(args, 0, sipArg0); if (sipArg1 != NULL) { Py_INCREF(sipArg1); PyTuple_SET_ITEM(args, 1, sipArg1); } /* * The first pass checks all the types and does conversions that are cheap * and have no side effects. */ va_start(va, fmt); ok = parsePass1(parseErrp, &self, &selfarg, args, NULL, NULL, NULL, fmt, va); va_end(va); if (ok) { /* * The second pass does any remaining conversions now that we know we * have the right signature. */ va_start(va, fmt); ok = parsePass2(self, selfarg, args, NULL, NULL, fmt, va); va_end(va); /* Remove any previous failed parses. */ Py_XDECREF(*parseErrp); if (ok) { *parseErrp = NULL; } else { /* Indicate that an exception has been raised. */ *parseErrp = Py_None; Py_INCREF(Py_None); } } Py_DECREF(args); return ok; } /* * First pass of the argument parse, converting those that can be done so * without any side effects. Return TRUE if the arguments matched. */ static int parsePass1(PyObject **parseErrp, PyObject **selfp, int *selfargp, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, PyObject **unused, const char *fmt, va_list va) { int compulsory, argnr, nr_args; Py_ssize_t nr_pos_args, nr_kwd_args, nr_kwd_args_used; sipParseFailure failure; failure.reason = Ok; failure.detail_obj = NULL; compulsory = TRUE; argnr = 0; nr_args = 0; nr_pos_args = PyTuple_GET_SIZE(sipArgs); nr_kwd_args = nr_kwd_args_used = 0; if (sipKwdArgs != NULL) { assert(PyDict_Check(sipKwdArgs)); nr_kwd_args = PyDict_Size(sipKwdArgs); } /* * Handle those format characters that deal with the "self" argument. They * will always be the first one. */ *selfp = NULL; *selfargp = FALSE; switch (*fmt++) { case 'B': case 'p': { PyObject *self; sipTypeDef *td; self = *va_arg(va, PyObject **); td = va_arg(va, sipTypeDef *); va_arg(va, void **); if (PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type)) { /* The call was self.method(...). */ *selfp = self; } else if (getSelfFromArgs(td, sipArgs, argnr, selfp)) { /* The call was cls.method(self, ...). */ *selfargp = TRUE; ++argnr; } else { failure.reason = Unbound; failure.detail_str = sipPyNameOfContainer( &((sipClassTypeDef *)td)->ctd_container, td); } break; } case 'C': { PyObject *self; self = *va_arg(va, PyObject **); /* * If the call was self.method(...) rather than cls.method(...) * then get cls from self. */ if (PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) self = (PyObject *)Py_TYPE(self); *selfp = self; break; } default: --fmt; } /* * Now handle the remaining arguments. We continue to parse if we get an * overflow because that is, strictly speaking, a second pass error. */ while (failure.reason == Ok || failure.reason == Overflow) { char ch; PyObject *arg; PyErr_Clear(); /* See if the following arguments are optional. */ if ((ch = *fmt++) == '|') { compulsory = FALSE; ch = *fmt++; } /* See if we don't expect anything else. */ if (ch == '\0') { if (argnr < nr_pos_args) { /* There are still positional arguments. */ failure.reason = TooMany; } else if (nr_kwd_args_used != nr_kwd_args) { /* * Take a shortcut if no keyword arguments were used and we are * interested in them. */ if (nr_kwd_args_used == 0 && unused != NULL) { Py_INCREF(sipKwdArgs); *unused = sipKwdArgs; } else { PyObject *key, *value, *unused_dict = NULL; Py_ssize_t pos = 0; /* * Go through the keyword arguments to find any that were * duplicates of positional arguments. For the remaining * ones remember the unused ones if we are interested. */ while (PyDict_Next(sipKwdArgs, &pos, &key, &value)) { int a; if (!PyUnicode_Check(key)) { failure.reason = KeywordNotString; failure.detail_obj = key; Py_INCREF(key); break; } if (kwdlist != NULL) { /* Get the argument's index if it is one. */ for (a = 0; a < nr_args; ++a) { const char *name = kwdlist[a]; if (name == NULL) continue; if (PyUnicode_CompareWithASCIIString(key, name) == 0) break; } } else { a = nr_args; } if (a == nr_args) { /* * The name doesn't correspond to a keyword * argument. */ if (unused == NULL) { /* * It may correspond to a keyword argument of a * different overload. */ failure.reason = UnknownKeyword; failure.detail_obj = key; Py_INCREF(key); break; } /* * Add it to the dictionary of unused arguments * creating it if necessary. Note that if the * unused arguments are actually used by a later * overload then the parse will incorrectly * succeed. This should be picked up (perhaps with * a misleading exception) so long as the code that * handles the unused arguments checks that it can * handle them all. */ if (unused_dict == NULL && (*unused = unused_dict = PyDict_New()) == NULL) { failure.reason = Raised; break; } if (PyDict_SetItem(unused_dict, key, value) < 0) { failure.reason = Raised; break; } } else if (a < nr_pos_args - *selfargp) { /* * The argument has been given positionally and as * a keyword. */ failure.reason = Duplicate; failure.detail_obj = key; Py_INCREF(key); break; } } } } break; } /* Get the next argument. */ arg = NULL; failure.arg_nr = -1; failure.arg_name = NULL; if (argnr < nr_pos_args) { arg = PyTuple_GET_ITEM(sipArgs, argnr); failure.arg_nr = argnr + 1; } else if (nr_kwd_args != 0 && kwdlist != NULL) { const char *name = kwdlist[argnr - *selfargp]; if (name != NULL) { arg = PyDict_GetItemString(sipKwdArgs, name); if (arg != NULL) ++nr_kwd_args_used; failure.arg_name = name; } } ++argnr; ++nr_args; if (arg == NULL && compulsory) { if (ch == 'W') { /* * A variable number of arguments was allowed but none were * given. */ break; } /* An argument was required. */ failure.reason = TooFew; /* * Check if there were any unused keyword arguments so that we give * a (possibly) more accurate diagnostic in the case that a keyword * argument has been mis-spelled. */ if (unused == NULL && sipKwdArgs != NULL && nr_kwd_args_used != nr_kwd_args) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(sipKwdArgs, &pos, &key, &value)) { int a; if (!PyUnicode_Check(key)) { failure.reason = KeywordNotString; failure.detail_obj = key; Py_INCREF(key); break; } if (kwdlist != NULL) { /* Get the argument's index if it is one. */ for (a = 0; a < nr_args; ++a) { const char *name = kwdlist[a]; if (name == NULL) continue; if (PyUnicode_CompareWithASCIIString(key, name) == 0) break; } } else { a = nr_args; } if (a == nr_args) { failure.reason = UnknownKeyword; failure.detail_obj = key; Py_INCREF(key); break; } } } break; } /* * Handle the format character even if we don't have an argument so * that we skip the right number of arguments. */ switch (ch) { case 'W': /* Ellipsis. */ break; case '@': { /* Implement /GetWrapper/. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) *p = arg; /* Process the same argument next time round. */ --argnr; --nr_args; break; } case 's': { /* String from a Python bytes or None. */ const char **p = va_arg(va, const char **); if (arg != NULL && parseBytes_AsString(arg, p) < 0) handle_failed_type_conversion(&failure, arg); break; } case 'A': { /* String from a Python string or None. */ va_arg(va, PyObject **); va_arg(va, const char **); fmt++; if (arg != NULL && check_encoded_string(arg) < 0) handle_failed_type_conversion(&failure, arg); break; } case 'a': { /* Character from a Python string. */ va_arg(va, char *); fmt++; if (arg != NULL && check_encoded_string(arg) < 0) handle_failed_type_conversion(&failure, arg); break; } case 'x': #if defined(HAVE_WCHAR_H) { /* Wide string or None. */ wchar_t **p = va_arg(va, wchar_t **); if (arg != NULL && parseWCharString(arg, p) < 0) handle_failed_type_conversion(&failure, arg); break; } #else raiseNoWChar(); failure.reason = Raised; break; #endif case 'r': { /* Sequence of class or mapped type instances. */ const sipTypeDef *td; td = va_arg(va, const sipTypeDef *); va_arg(va, void **); va_arg(va, Py_ssize_t *); if (arg != NULL && !canConvertFromSequence(arg, td)) handle_failed_type_conversion(&failure, arg); break; } case 'J': { /* Class or mapped type instance. */ char sub_fmt = *fmt++; const sipTypeDef *td; int flags = sub_fmt - '0'; int iflgs = 0; td = va_arg(va, const sipTypeDef *); va_arg(va, void **); if (flags & FMT_AP_DEREF) iflgs |= SIP_NOT_NONE; if (flags & FMT_AP_TRANSFER_THIS) va_arg(va, PyObject **); if (flags & FMT_AP_NO_CONVERTORS) iflgs |= SIP_NO_CONVERTORS; else va_arg(va, int *); if (sipTypeNeedsUserState(td)) va_arg(va, void **); if (arg != NULL && !sip_api_can_convert_to_type(arg, td, iflgs)) handle_failed_type_conversion(&failure, arg); break; } case 'N': { /* Python object of given type or None. */ PyTypeObject *type = va_arg(va,PyTypeObject *); PyObject **p = va_arg(va,PyObject **); if (arg != NULL) { if (arg == Py_None || PyObject_TypeCheck(arg,type)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case 'P': { /* Python object of any type with a sub-format. */ va_arg(va, PyObject **); /* Skip the sub-format. */ ++fmt; break; } case 'T': { /* Python object of given type. */ PyTypeObject *type = va_arg(va, PyTypeObject *); PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (PyObject_TypeCheck(arg,type)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case 'F': { /* Python callable object. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (PyCallable_Check(arg)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case 'H': { /* Python callable object or None. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (arg == Py_None || PyCallable_Check(arg)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case '!': { /* Python object that implements the buffer protocol. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (PyObject_CheckBuffer(arg)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case '$': { /* * Python object that implements the buffer protocol or None. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (arg == Py_None || PyObject_CheckBuffer(arg)) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case '&': { /* Python enum.Enum object. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (PyObject_IsSubclass(arg, enum_type) == 1) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case '^': { /* * Python enum.Enum object or None. */ PyObject **p = va_arg(va, PyObject **); if (arg != NULL) { if (arg == Py_None || PyObject_IsSubclass(arg, enum_type) == 1) *p = arg; else handle_failed_type_conversion(&failure, arg); } break; } case 'k': { /* Char array or None. */ const char **p = va_arg(va, const char **); Py_ssize_t *szp = va_arg(va, Py_ssize_t *); if (arg != NULL && parseBytes_AsCharArray(arg, p, szp) < 0) handle_failed_type_conversion(&failure, arg); break; } case 'K': #if defined(HAVE_WCHAR_H) { /* Wide char array or None. */ wchar_t **p = va_arg(va, wchar_t **); Py_ssize_t *szp = va_arg(va, Py_ssize_t *); if (arg != NULL && parseWCharArray(arg, p, szp) < 0) handle_failed_type_conversion(&failure, arg); break; } #else raiseNoWChar(); failure.reason = Raised; break #endif case 'c': { /* Character from a Python bytes. */ char *p = va_arg(va, char *); if (arg != NULL && parseBytes_AsChar(arg, p) < 0) handle_failed_type_conversion(&failure, arg); break; } case 'w': #if defined(HAVE_WCHAR_H) { /* Wide character. */ wchar_t *p = va_arg(va, wchar_t *); if (arg != NULL && parseWChar(arg, p) < 0) handle_failed_type_conversion(&failure, arg); break; } #else raiseNoWChar(); failure.reason = Raised; break #endif case 'b': { /* Bool. */ void *p = va_arg(va, void *); if (arg != NULL) { int v = sip_api_convert_to_bool(arg); if (v < 0) handle_failed_type_conversion(&failure, arg); else sipSetBool(p, v); } break; } case 'E': { /* Named or scoped enum. */ sipTypeDef *td = va_arg(va, sipTypeDef *); int *p = va_arg(va, int *); if (arg != NULL) { int v = sip_api_convert_to_enum(arg, td); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); else *p = v; } } break; case 'e': { /* Anonymous enum. */ int *p = va_arg(va, int *); if (arg != NULL) { int v = sip_api_long_as_int(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } } break; case 'i': { /* Integer. */ int *p = va_arg(va, int *); if (arg != NULL) { int v = sip_api_long_as_int(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'u': { /* Unsigned integer. */ unsigned *p = va_arg(va, unsigned *); if (arg != NULL) { unsigned v = sip_api_long_as_unsigned_int(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case '=': { /* size_t integer. */ size_t *p = va_arg(va, size_t *); if (arg != NULL) { size_t v = sip_api_long_as_size_t(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'L': { /* Signed char. */ signed char *p = va_arg(va, signed char *); if (arg != NULL) { signed char v = sip_api_long_as_signed_char(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'M': { /* Unsigned char. */ unsigned char *p = va_arg(va, unsigned char *); if (arg != NULL) { unsigned char v = sip_api_long_as_unsigned_char(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'h': { /* Short integer. */ signed short *p = va_arg(va, signed short *); if (arg != NULL) { signed short v = sip_api_long_as_short(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 't': { /* Unsigned short integer. */ unsigned short *p = va_arg(va, unsigned short *); if (arg != NULL) { unsigned short v = sip_api_long_as_unsigned_short(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'l': { /* Long integer. */ long *p = va_arg(va, long *); if (arg != NULL) { long v = sip_api_long_as_long(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'm': { /* Unsigned long integer. */ unsigned long *p = va_arg(va, unsigned long *); if (arg != NULL) { unsigned long v = sip_api_long_as_unsigned_long(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'n': { /* Long long integer. */ long long *p = va_arg(va, long long *); if (arg != NULL) { long long v = sip_api_long_as_long_long(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'o': { /* Unsigned long long integer. */ unsigned long long *p = va_arg(va, unsigned long long *); if (arg != NULL) { unsigned long long v = sip_api_long_as_unsigned_long_long(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); else *p = v; } break; } case 'f': { /* Float. */ float *p = va_arg(va, float *); if (arg != NULL) { double v = PyFloat_AsDouble(arg); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); else *p = (float)v; } break; } case 'X': { /* Constrained types. */ char sub_fmt = *fmt++; if (sub_fmt == 'E') { /* * Named or scoped enum. Note that in this version of the * ABI there is no difference between constrained and * unconstrained enums. */ sipTypeDef *td = va_arg(va, sipTypeDef *); int *p = va_arg(va, int *); if (arg != NULL) { *p = sip_api_convert_to_enum(arg, td); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); } } else { void *p = va_arg(va, void *); if (arg != NULL) { switch (sub_fmt) { case 'b': { /* Boolean. */ if (PyBool_Check(arg)) sipSetBool(p, (arg == Py_True)); else handle_failed_type_conversion(&failure, arg); break; } case 'd': { /* Double float. */ if (PyFloat_Check(arg)) *(double *)p = PyFloat_AS_DOUBLE(arg); else handle_failed_type_conversion(&failure, arg); break; } case 'f': { /* Float. */ if (PyFloat_Check(arg)) *(float *)p = (float)PyFloat_AS_DOUBLE(arg); else handle_failed_type_conversion(&failure, arg); break; } case 'i': { /* Integer. */ if (PyLong_Check(arg)) { *(int *)p = sip_api_long_as_int(arg); if (PyErr_Occurred()) handle_failed_int_conversion(&failure, arg); } else { handle_failed_type_conversion(&failure, arg); } break; } } } } break; } case 'd': { /* Double float. */ double *p = va_arg(va,double *); if (arg != NULL) { double v = PyFloat_AsDouble(arg); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); else *p = v; } break; } case 'v': { /* Void pointer. */ void **p = va_arg(va, void **); if (arg != NULL) { void *v = sip_api_convert_to_void_ptr(arg); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); else *p = v; } break; } case 'z': { /* Void pointer as a capsule. */ const char *name = va_arg(va, const char *); void **p = va_arg(va, void **); if (arg == Py_None) { *p = NULL; } else if (arg != NULL) { void *v = PyCapsule_GetPointer(arg, name); if (PyErr_Occurred()) handle_failed_type_conversion(&failure, arg); else *p = v; } break; } } if ((failure.reason == Ok || failure.reason == Overflow) && ch == 'W') { /* An ellipsis matches everything and ends the parse. */ break; } } /* Handle parse failures appropriately. */ if (failure.reason == Ok) return TRUE; if (failure.reason == Overflow) { /* * We have successfully parsed the signature but one of the arguments * has been found to overflow. Raise an appropriate exception and * ensure we don't parse any subsequent overloads. */ if (failure.overflow_arg_nr >= 0) { PyErr_Format(PyExc_OverflowError, "argument %d overflowed: %S", failure.overflow_arg_nr, failure.detail_obj); } else { PyErr_Format(PyExc_OverflowError, "argument '%s' overflowed: %S", failure.overflow_arg_name, failure.detail_obj); } /* The overflow exception has now been raised. */ failure.reason = Raised; } if (failure.reason != Raised) add_failure(parseErrp, &failure); if (failure.reason == Raised) { Py_XDECREF(failure.detail_obj); /* * Discard any previous errors and flag that the exception we want the * user to see has been raised. */ Py_XDECREF(*parseErrp); *parseErrp = Py_None; Py_INCREF(Py_None); } return FALSE; } /* * Called after a failed conversion of an integer. */ static void handle_failed_int_conversion(sipParseFailure *pf, PyObject *arg) { PyObject *xtype, *xvalue, *xtb; assert(pf->reason == Ok || pf->reason == Overflow); PyErr_Fetch(&xtype, &xvalue, &xtb); if (PyErr_GivenExceptionMatches(xtype, PyExc_OverflowError) && xvalue != NULL) { /* Remove any previous overflow exception. */ Py_XDECREF(pf->detail_obj); pf->reason = Overflow; pf->overflow_arg_nr = pf->arg_nr; pf->overflow_arg_name = pf->arg_name; pf->detail_obj = xvalue; Py_INCREF(xvalue); } else { handle_failed_type_conversion(pf, arg); } PyErr_Restore(xtype, xvalue, xtb); } /* * Called after a failed conversion of a type. */ static void handle_failed_type_conversion(sipParseFailure *pf, PyObject *arg) { pf->reason = WrongType; pf->detail_obj = arg; Py_INCREF(arg); } /* * Second pass of the argument parse, converting the remaining ones that might * have side effects. Return TRUE if there was no error. */ static int parsePass2(PyObject *self, int selfarg, PyObject *sipArgs, PyObject *sipKwdArgs, const char **kwdlist, const char *fmt, va_list va) { int a, ok, isstatic = FALSE; Py_ssize_t nr_pos_args; /* Handle the conversions of "self" first. */ switch (*fmt++) { case 'B': { /* * The address of a C++ instance when calling one of its public * methods. */ const sipTypeDef *td; void **p; *va_arg(va, PyObject **) = self; td = va_arg(va, const sipTypeDef *); p = va_arg(va, void **); if ((*p = sip_api_get_cpp_ptr((sipSimpleWrapper *)self, td)) == NULL) return FALSE; break; } case 'p': { /* * The address of a C++ instance when calling one of its protected * methods. */ const sipTypeDef *td; void **p; *va_arg(va, PyObject **) = self; td = va_arg(va, const sipTypeDef *); p = va_arg(va, void **); if ((*p = getComplexCppPtr((sipSimpleWrapper *)self, td)) == NULL) return FALSE; break; } case 'C': *va_arg(va, PyObject **) = self; isstatic = TRUE; break; default: --fmt; } ok = TRUE; nr_pos_args = PyTuple_GET_SIZE(sipArgs); for (a = (selfarg ? 1 : 0); *fmt != '\0' && *fmt != 'W' && ok; ++a) { char ch; PyObject *arg; /* Skip the optional character. */ if ((ch = *fmt++) == '|') ch = *fmt++; /* Get the next argument. */ arg = NULL; if (a < nr_pos_args) { arg = PyTuple_GET_ITEM(sipArgs, a); } else if (sipKwdArgs != NULL) { const char *name = kwdlist[a - selfarg]; if (name != NULL) arg = PyDict_GetItemString(sipKwdArgs, name); } /* * Do the outstanding conversions. For most types it has already been * done, so we are just skipping the parameters. */ switch (ch) { case '@': /* Implement /GetWrapper/. */ va_arg(va, PyObject **); /* Process the same argument next time round. */ --a; break; case 'r': { /* Sequence of class or mapped type instances. */ const sipTypeDef *td; void **array; Py_ssize_t *nr_elem; td = va_arg(va, const sipTypeDef *); array = va_arg(va, void **); nr_elem = va_arg(va, Py_ssize_t *); if (arg != NULL && !convertFromSequence(arg, td, array, nr_elem)) return FALSE; break; } case 'J': { /* Class or mapped type instance. */ int flags = *fmt++ - '0'; const sipTypeDef *td; void **p; int iflgs = 0; int *statep; PyObject *xfer, **owner; void **user_statep; td = va_arg(va, const sipTypeDef *); p = va_arg(va, void **); if (flags & FMT_AP_TRANSFER) xfer = (isstatic ? arg : self); else if (flags & FMT_AP_TRANSFER_BACK) xfer = Py_None; else xfer = NULL; if (flags & FMT_AP_DEREF) iflgs |= SIP_NOT_NONE; if (flags & FMT_AP_TRANSFER_THIS) owner = va_arg(va, PyObject **); if (flags & FMT_AP_NO_CONVERTORS) { iflgs |= SIP_NO_CONVERTORS; statep = NULL; } else { statep = va_arg(va, int *); } if (sipTypeNeedsUserState(td)) user_statep = va_arg(va, void **); else user_statep = NULL; if (arg != NULL) { int iserr = FALSE; *p = sip_api_convert_to_type_us(arg, td, xfer, iflgs, statep, user_statep, &iserr); if (iserr) return FALSE; if (flags & FMT_AP_TRANSFER_THIS && *p != NULL) *owner = arg; } break; } case 'P': { /* Python object of any type with a sub-format. */ PyObject **p = va_arg(va, PyObject **); int flags = *fmt++ - '0'; if (arg != NULL) { if (flags & FMT_AP_TRANSFER) { Py_XINCREF(arg); } else if (flags & FMT_AP_TRANSFER_BACK) { Py_XDECREF(arg); } *p = arg; } break; } case 'X': { /* Constrained types. */ if (*fmt++ == 'E') va_arg(va, void *); va_arg(va, void *); break; } case 'A': { /* String from a Python string or None. */ PyObject **keep = va_arg(va, PyObject **); const char **p = va_arg(va, const char **); char sub_fmt = *fmt++; if (arg != NULL) { PyObject *s = NULL; switch (sub_fmt) { case 'A': s = parseString_AsASCIIString(arg, p); break; case 'L': s = parseString_AsLatin1String(arg, p); break; case '8': s = parseString_AsUTF8String(arg, p); break; } if (s == NULL) return FALSE; *keep = s; } break; } case 'a': { /* Character from a Python string. */ char *p = va_arg(va, char *); char sub_fmt = *fmt++; if (arg != NULL) { int enc; switch (sub_fmt) { case 'A': enc = parseString_AsASCIIChar(arg, p); break; case 'L': enc = parseString_AsLatin1Char(arg, p); break; case '8': enc = parseString_AsUTF8Char(arg, p); break; } if (enc < 0) return FALSE; } break; } /* * Every other argument is a pointer and only differ in how many there * are. */ case 'N': case 'T': case 'k': case 'K': case 'U': case 'E': va_arg(va, void *); /* Drop through. */ default: va_arg(va, void *); } } /* Handle any ellipsis argument. */ if (*fmt == 'W') { PyObject *al; int da = 0; /* Create a tuple for any remaining arguments. */ if ((al = PyTuple_New(nr_pos_args - a)) == NULL) return FALSE; while (a < nr_pos_args) { PyObject *arg = PyTuple_GET_ITEM(sipArgs, a); /* Add the remaining argument to the tuple. */ Py_INCREF(arg); PyTuple_SET_ITEM(al, da, arg); ++a; ++da; } /* Return the tuple. */ *va_arg(va, PyObject **) = al; } return TRUE; } /* * See if a Python object is a sequence of a particular type. */ static int canConvertFromSequence(PyObject *seq, const sipTypeDef *td) { Py_ssize_t i, size = PySequence_Size(seq); if (size < 0) return FALSE; for (i = 0; i < size; ++i) { int ok; PyObject *val_obj; if ((val_obj = PySequence_GetItem(seq, i)) == NULL) return FALSE; ok = sip_api_can_convert_to_type(val_obj, td, SIP_NO_CONVERTORS|SIP_NOT_NONE); Py_DECREF(val_obj); if (!ok) return FALSE; } return TRUE; } /* * Convert a Python sequence to an array that has already "passed" * canConvertFromSequence(). Return TRUE if the conversion was successful. */ static int convertFromSequence(PyObject *seq, const sipTypeDef *td, void **array, Py_ssize_t *nr_elem) { int iserr = 0; Py_ssize_t i, size = PySequence_Size(seq); sipArrayFunc array_helper; sipAssignFunc assign_helper; void *array_mem; /* Get the type's helpers. */ if (sipTypeIsMapped(td)) { array_helper = ((const sipMappedTypeDef *)td)->mtd_array; assign_helper = ((const sipMappedTypeDef *)td)->mtd_assign; } else { array_helper = ((const sipClassTypeDef *)td)->ctd_array; assign_helper = ((const sipClassTypeDef *)td)->ctd_assign; } assert(array_helper != NULL); assert(assign_helper != NULL); /* * Create the memory for the array of values. Note that this will leak if * there is an error. */ array_mem = array_helper(size); for (i = 0; i < size; ++i) { PyObject *val_obj; void *val; if ((val_obj = PySequence_GetItem(seq, i)) == NULL) return FALSE; val = sip_api_convert_to_type_us(val_obj, td, NULL, SIP_NO_CONVERTORS|SIP_NOT_NONE, NULL, NULL, &iserr); Py_DECREF(val_obj); if (iserr) return FALSE; assign_helper(array_mem, i, val); } *array = array_mem; *nr_elem = size; return TRUE; } /* * Convert an array of a type to a Python sequence. */ static PyObject *convertToSequence(void *array, Py_ssize_t nr_elem, const sipTypeDef *td) { Py_ssize_t i; PyObject *seq; sipCopyFunc copy_helper; /* Get the type's copy helper. */ if (sipTypeIsMapped(td)) copy_helper = ((const sipMappedTypeDef *)td)->mtd_copy; else copy_helper = ((const sipClassTypeDef *)td)->ctd_copy; assert(copy_helper != NULL); if ((seq = PyTuple_New(nr_elem)) == NULL) return NULL; for (i = 0; i < nr_elem; ++i) { void *el = copy_helper(array, i); PyObject *el_obj = sip_api_convert_from_new_type(el, td, NULL); if (el_obj == NULL) { release(el, td, 0, NULL); Py_DECREF(seq); } PyTuple_SET_ITEM(seq, i, el_obj); } return seq; } /* * Perform housekeeping after a C++ instance has been destroyed. */ void sip_api_instance_destroyed(sipSimpleWrapper *sw) { sip_api_instance_destroyed_ex(&sw); } /* * Carry out actions common to all dtors. */ static void sip_api_instance_destroyed_ex(sipSimpleWrapper **sipSelfp) { /* If there is no interpreter just to the minimum and get out. */ if (sipInterpreter == NULL) { *sipSelfp = NULL; return; } SIP_BLOCK_THREADS sipSimpleWrapper *sipSelf = *sipSelfp; if (sipSelf != NULL) { PyObject *xtype, *xvalue, *xtb; /* We may be tidying up after an exception so preserve it. */ PyErr_Fetch(&xtype, &xvalue, &xtb); callPyDtor(sipSelf); PyErr_Restore(xtype, xvalue, xtb); sipOMRemoveObject(&cppPyMap, sipSelf); /* * This no longer points to anything useful. Actually it might do as * the partialy destroyed C++ instance may still be trying to invoke * reimplemented virtuals. */ clear_access_func(sipSelf); /* * If C/C++ has a reference (and therefore no parent) then remove it. * Otherwise remove the object from any parent. */ if (sipCppHasRef(sipSelf)) { sipResetCppHasRef(sipSelf); Py_DECREF(sipSelf); } else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)&sipWrapper_Type)) { removeFromParent((sipWrapper *)sipSelf); } /* * Normally this is done in the generated dealloc function. However * this is only called if the pointer/access function has not been * reset (which it has). It acts as a guard to prevent any further * invocations of reimplemented virtuals. */ *sipSelfp = NULL; } SIP_UNBLOCK_THREADS } /* * Clear any access function so that sip_api_get_address() will always return a * NULL pointer. */ static void clear_access_func(sipSimpleWrapper *sw) { if (sw->access_func != NULL) { sw->access_func(sw, ReleaseGuard); sw->access_func = NULL; } sw->data = NULL; } /* * Call self.__dtor__() if it is implemented. */ static void callPyDtor(sipSimpleWrapper *self) { sip_gilstate_t sipGILState; char pymc = 0; PyObject *meth; meth = sip_api_is_py_method_12_8(&sipGILState, &pymc, &self, NULL, "__dtor__"); if (meth != NULL) { PyObject *res = sip_api_call_method(0, meth, "", NULL); Py_DECREF(meth); /* Discard any result. */ Py_XDECREF(res); /* Handle any error the best we can. */ if (PyErr_Occurred()) PyErr_Print(); SIP_RELEASE_GIL(sipGILState); } } /* * Add a wrapper to it's parent owner. The wrapper must not currently have a * parent and, therefore, no siblings. */ static void addToParent(sipWrapper *self, sipWrapper *owner) { if (owner->first_child != NULL) { self->sibling_next = owner->first_child; owner->first_child->sibling_prev = self; } owner->first_child = self; self->parent = owner; /* * The owner holds a real reference so that the cyclic garbage collector * works properly. */ Py_INCREF((sipSimpleWrapper *)self); } /* * Remove a wrapper from it's parent if it has one. */ static void removeFromParent(sipWrapper *self) { if (self->parent != NULL) { if (self->parent->first_child == self) self->parent->first_child = self->sibling_next; if (self->sibling_next != NULL) self->sibling_next->sibling_prev = self->sibling_prev; if (self->sibling_prev != NULL) self->sibling_prev->sibling_next = self->sibling_next; self->parent = NULL; self->sibling_next = NULL; self->sibling_prev = NULL; /* * We must do this last, after all the pointers are correct, because * this is used by the clear slot. */ Py_DECREF((sipSimpleWrapper *)self); } } /* * Detach and children of a parent. */ static void detachChildren(sipWrapper *self) { while (self->first_child != NULL) removeFromParent(self->first_child); } /* * Convert a sequence index. Return the index or a negative value if there was * an error. */ static Py_ssize_t sip_api_convert_from_sequence_index(Py_ssize_t idx, Py_ssize_t len) { /* Negative indices start from the other end. */ if (idx < 0) idx = len + idx; if (idx < 0 || idx >= len) { PyErr_Format(PyExc_IndexError, "sequence index out of range"); return -1; } return idx; } /* * Return a tuple of the base class of a type that has no explicit super-type. */ static PyObject *getDefaultBase(void) { static PyObject *default_base = NULL; /* Only do this once. */ if (default_base == NULL) { if ((default_base = PyTuple_Pack(1, (PyObject *)&sipWrapper_Type)) == NULL) return NULL; } Py_INCREF(default_base); return default_base; } /* * Return a tuple of the base class of a simple type that has no explicit * super-type. */ static PyObject *getDefaultSimpleBase(void) { static PyObject *default_simple_base = NULL; /* Only do this once. */ if (default_simple_base == NULL) { if ((default_simple_base = PyTuple_Pack(1, (PyObject *)&sipSimpleWrapper_Type)) == NULL) return NULL; } Py_INCREF(default_simple_base); return default_simple_base; } /* * Return the dictionary of a type. */ static PyObject *getScopeDict(sipTypeDef *td, PyObject *mod_dict, sipExportedModuleDef *client) { /* * Initialise the scoping type if necessary. It will always be in the * same module if it needs doing. */ if (sipTypeIsMapped(td)) { if (createMappedType(client, (sipMappedTypeDef *)td, mod_dict) < 0) return NULL; /* Check that the mapped type can act as a container. */ assert(sipTypeAsPyTypeObject(td) != NULL); } else { if (createClassType(client, (sipClassTypeDef *)td, mod_dict) < 0) return NULL; } return (sipTypeAsPyTypeObject(td))->tp_dict; } /* * Create a container type and return a borrowed reference to it. */ static PyObject *createContainerType(sipContainerDef *cod, sipTypeDef *td, PyObject *bases, PyObject *metatype, PyObject *mod_dict, PyObject *type_dict, sipExportedModuleDef *client) { PyObject *py_type, *scope_dict, *name, *args; sipTypeDef *scope_td; /* Get the dictionary to place the type in. */ if (cod->cod_scope.sc_flag) { scope_td = NULL; scope_dict = mod_dict; } else { scope_td = getGeneratedType(&cod->cod_scope, client); scope_dict = getScopeDict(scope_td, mod_dict, client); if (scope_dict == NULL) goto reterr; } /* Create an object corresponding to the type name. */ if ((name = PyUnicode_FromString(sipPyNameOfContainer(cod, td))) == NULL) goto reterr; /* Create the type by calling the metatype. */ if ((args = PyTuple_Pack(3, name, bases, type_dict)) == NULL) goto relname; /* Pass the type via the back door. */ assert(currentType == NULL); currentType = td; py_type = PyObject_Call(metatype, args, NULL); currentType = NULL; if (py_type == NULL) goto relargs; /* Fix __qualname__ if there is a scope. */ if (scope_td != NULL) { PyHeapTypeObject *ht; PyObject *qualname = get_qualname(scope_td, name); if (qualname == NULL) goto reltype; ht = (PyHeapTypeObject *)py_type; Py_CLEAR(ht->ht_qualname); ht->ht_qualname = qualname; } /* Add the type to the "parent" dictionary. */ if (PyDict_SetItem(scope_dict, name, py_type) < 0) goto reltype; Py_DECREF(args); Py_DECREF(name); return py_type; /* Unwind on error. */ reltype: Py_DECREF(py_type); relargs: Py_DECREF(args); relname: Py_DECREF(name); reterr: return NULL; } /* * Create a single class type object. */ static int createClassType(sipExportedModuleDef *client, sipClassTypeDef *ctd, PyObject *mod_dict) { PyObject *bases, *metatype, *py_type, *type_dict; sipEncodedTypeDef *sup; int i; /* Handle the trivial case where we have already been initialised. */ if (ctd->ctd_base.td_module != NULL) return 0; /* Set this up now to gain access to the string pool. */ ctd->ctd_base.td_module = client; /* Create the tuple of super-types. */ if ((sup = ctd->ctd_supers) == NULL) { if (ctd->ctd_supertype < 0) { bases = (sipTypeIsNamespace(&ctd->ctd_base) ? getDefaultSimpleBase() : getDefaultBase()); } else { PyObject *supertype; const char *supertype_name = sipNameFromPool(client, ctd->ctd_supertype); if ((supertype = findPyType(supertype_name)) == NULL) goto reterr; bases = PyTuple_Pack(1, supertype); } if (bases == NULL) goto reterr; } else { int nrsupers = 0; do ++nrsupers; while (!sup++->sc_flag); if ((bases = PyTuple_New(nrsupers)) == NULL) goto reterr; for (sup = ctd->ctd_supers, i = 0; i < nrsupers; ++i, ++sup) { PyObject *st; sipTypeDef *sup_td = getGeneratedType(sup, client); /* * Initialise the super-class if necessary. It will always be in * the same module if it needs doing. */ if (createClassType(client, (sipClassTypeDef *)sup_td, mod_dict) < 0) goto relbases; st = (PyObject *)sipTypeAsPyTypeObject(sup_td); Py_INCREF(st); PyTuple_SET_ITEM(bases, i, st); /* * Inherit any garbage collector code rather than look for it each * time it is needed. */ if (ctd->ctd_traverse == NULL) ctd->ctd_traverse = ((sipClassTypeDef *)sup_td)->ctd_traverse; if (ctd->ctd_clear == NULL) ctd->ctd_clear = ((sipClassTypeDef *)sup_td)->ctd_clear; } } /* * Use the explicit meta-type if there is one, otherwise use the meta-type * of the first super-type. */ if (ctd->ctd_metatype >= 0) { const char *metatype_name = sipNameFromPool(client, ctd->ctd_metatype); if ((metatype = findPyType(metatype_name)) == NULL) goto relbases; } else metatype = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(bases, 0)); /* Create the type dictionary and populate it with any non-lazy methods. */ if ((type_dict = createTypeDict(client)) == NULL) goto relbases; if (sipTypeHasNonlazyMethod(&ctd->ctd_base)) { PyMethodDef *pmd = ctd->ctd_container.cod_methods; for (i = 0; i < ctd->ctd_container.cod_nrmethods; ++i) { if (isNonlazyMethod(pmd) && addMethod(type_dict, pmd) < 0) goto reldict; ++pmd; } } if ((py_type = createContainerType(&ctd->ctd_container, (sipTypeDef *)ctd, bases, metatype, mod_dict, type_dict, client)) == NULL) goto reldict; if (ctd->ctd_pyslots != NULL) fix_slots((PyTypeObject *)py_type, ctd->ctd_pyslots); /* Handle the pickle function. */ if (ctd->ctd_pickle != NULL) { static PyMethodDef md = { "_pickle_type", pickle_type, METH_NOARGS, NULL }; if (setReduce((PyTypeObject *)py_type, &md) < 0) goto reltype; } /* We can now release our references. */ Py_DECREF(bases); Py_DECREF(type_dict); return 0; /* Unwind after an error. */ reltype: Py_DECREF(py_type); reldict: Py_DECREF(type_dict); relbases: Py_DECREF(bases); reterr: ctd->ctd_base.td_module = NULL; return -1; } /* * Create a single mapped type object. */ static int createMappedType(sipExportedModuleDef *client, sipMappedTypeDef *mtd, PyObject *mod_dict) { PyObject *bases, *type_dict; /* Handle the trivial case where we have already been initialised. */ if (mtd->mtd_base.td_module != NULL) return 0; /* Set this up now to gain access to the string pool. */ mtd->mtd_base.td_module = client; /* Create the tuple of super-types. */ if ((bases = getDefaultBase()) == NULL) goto reterr; /* Create the type dictionary. */ if ((type_dict = createTypeDict(client)) == NULL) goto relbases; if (createContainerType(&mtd->mtd_container, (sipTypeDef *)mtd, bases, (PyObject *)&sipWrapperType_Type, mod_dict, type_dict, client) == NULL) goto reldict; /* We can now release our references. */ Py_DECREF(bases); Py_DECREF(type_dict); return 0; /* Unwind after an error. */ reldict: Py_DECREF(type_dict); relbases: Py_DECREF(bases); reterr: mtd->mtd_base.td_module = NULL; return -1; } /* * Return the module definition for a named module. */ static sipExportedModuleDef *getModule(PyObject *mname_obj) { PyObject *mod; sipExportedModuleDef *em; /* Make sure the module is imported. */ if ((mod = PyImport_Import(mname_obj)) == NULL) return NULL; /* Find the module definition. */ for (em = moduleList; em != NULL; em = em->em_next) if (PyUnicode_Compare(mname_obj, em->em_nameobj) == 0) break; Py_DECREF(mod); if (em == NULL) PyErr_Format(PyExc_SystemError, "unable to find to find module: %U", mname_obj); return em; } /* * The type unpickler. */ static PyObject *unpickle_type(PyObject *obj, PyObject *args) { PyObject *mname_obj, *init_args; const char *tname; sipExportedModuleDef *em; int i; (void)obj; if (!PyArg_ParseTuple(args, "UsO!:_unpickle_type", &mname_obj, &tname, &PyTuple_Type, &init_args)) return NULL; /* Get the module definition. */ if ((em = getModule(mname_obj)) == NULL) return NULL; /* Find the class type object. */ for (i = 0; i < em->em_nrtypes; ++i) { sipTypeDef *td = em->em_types[i]; if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td)) { const char *pyname = sipPyNameOfContainer( &((sipClassTypeDef *)td)->ctd_container, td); if (strcmp(pyname, tname) == 0) return PyObject_CallObject((PyObject *)sipTypeAsPyTypeObject(td), init_args); } } PyErr_Format(PyExc_SystemError, "unable to find to find type: %s", tname); return NULL; } /* * The type pickler. */ static PyObject *pickle_type(PyObject *obj, PyObject *args) { sipExportedModuleDef *em; (void)args; /* Find the type definition and defining module. */ for (em = moduleList; em != NULL; em = em->em_next) { int i; for (i = 0; i < em->em_nrtypes; ++i) { sipTypeDef *td = em->em_types[i]; if (td != NULL && !sipTypeIsStub(td) && sipTypeIsClass(td)) if (sipTypeAsPyTypeObject(td) == Py_TYPE(obj)) { PyObject *init_args; sipClassTypeDef *ctd = (sipClassTypeDef *)td; const char *pyname = sipPyNameOfContainer(&ctd->ctd_container, td); /* * Ask the handwritten pickle code for the tuple of * arguments that will recreate the object. */ init_args = ctd->ctd_pickle(sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, NULL)); if (init_args == NULL) return NULL; if (!PyTuple_Check(init_args)) { PyErr_Format(PyExc_TypeError, "%%PickleCode for type %s.%s did not return a tuple", sipNameOfModule(em), pyname); return NULL; } return Py_BuildValue("O(OsN)", type_unpickler, em->em_nameobj, pyname, init_args); } } } /* We should never get here. */ PyErr_Format(PyExc_SystemError, "attempt to pickle unknown type '%s'", Py_TYPE(obj)->tp_name); return NULL; } /* * Set the __reduce__method for a type. */ static int setReduce(PyTypeObject *type, PyMethodDef *pickler) { static PyObject *rstr = NULL; PyObject *descr; int rc; if (objectify("__reduce__", &rstr) < 0) return -1; /* Create the method descripter. */ if ((descr = PyDescr_NewMethod(type, pickler)) == NULL) return -1; /* * Save the method. Note that we don't use PyObject_SetAttr() as we want * to bypass any lazy attribute loading (which may not be safe yet). */ rc = PyType_Type.tp_setattro((PyObject *)type, rstr, descr); Py_DECREF(descr); return rc; } /* * Create an enum object. */ static int createEnum(sipExportedModuleDef *client, sipEnumTypeDef *etd, sipIntInstanceDef **next_int_p, PyObject *dict) { int rc; PyObject *name, *enum_obj; /* Create an object corresponding to the type name. */ if ((name = PyUnicode_FromString(sipPyNameOfEnum(etd))) == NULL) return -1; /* Create the enum object. */ if ((enum_obj = createEnumObject(client, etd, next_int_p, name)) == NULL) { Py_DECREF(name); return -1; } /* Add the enum to the "parent" dictionary. */ rc = PyDict_SetItem(dict, name, enum_obj); /* We can now release our remaining references. */ Py_DECREF(name); Py_DECREF(enum_obj); return rc; } /* * Create an enum object. */ static PyObject *createEnumObject(sipExportedModuleDef *client, sipEnumTypeDef *etd, sipIntInstanceDef **next_int_p, PyObject *name) { static PyObject *module_arg = NULL, *qualname_arg = NULL; int i; PyObject *members, *enum_factory, *enum_obj, *args, *kw_args, *etd_cap; sipIntInstanceDef *next_int; /* Create a dict of the members. */ if ((members = PyDict_New()) == NULL) goto ret_err; next_int = *next_int_p; assert(next_int != NULL); for (i = 0; i < etd->etd_nr_members; ++i) { PyObject *value_obj; assert(next_int->ii_name != NULL); /* Flags are implicitly unsigned. */ if (IS_UNSIGNED_ENUM(etd)) value_obj = PyLong_FromUnsignedLong((unsigned)next_int->ii_val); else value_obj = PyLong_FromLong(next_int->ii_val); if (dict_set_and_discard(members, next_int->ii_name, value_obj) < 0) goto rel_members; ++next_int; } *next_int_p = next_int; if ((args = PyTuple_Pack(2, name, members)) == NULL) goto rel_members; if ((kw_args = PyDict_New()) == NULL) goto rel_args; if (objectify("module", &module_arg) < 0) goto rel_kw_args; if (PyDict_SetItem(kw_args, module_arg, client->em_nameobj) < 0) goto rel_kw_args; /* * If the enum has a scope then the default __qualname__ will be incorrect. */ if (etd->etd_scope >= 0) { int rc; PyObject *qualname; if (objectify("qualname", &qualname_arg) < 0) goto rel_kw_args; if ((qualname = get_qualname(client->em_types[etd->etd_scope], name)) == NULL) goto rel_kw_args; rc = PyDict_SetItem(kw_args, qualname_arg, qualname); Py_DECREF(qualname); if (rc < 0) goto rel_kw_args; } /* Wrap the type definition in a capsule. */ if ((etd_cap = PyCapsule_New(etd, NULL, NULL)) == NULL) goto rel_kw_args; if (etd->etd_base_type == SIP_ENUM_INT_FLAG) enum_factory = int_flag_type; else if (etd->etd_base_type == SIP_ENUM_FLAG) enum_factory = flag_type; else if (etd->etd_base_type == SIP_ENUM_INT_ENUM || etd->etd_base_type == SIP_ENUM_UINT_ENUM) enum_factory = int_enum_type; else enum_factory = enum_type; if ((enum_obj = PyObject_Call(enum_factory, args, kw_args)) == NULL) goto rel_kw_args; Py_DECREF(kw_args); Py_DECREF(args); Py_DECREF(members); /* Note that it isn't actually a PyTypeObject. */ etd->etd_base.td_py_type = (PyTypeObject *)enum_obj; if (PyObject_SetAttrString(enum_obj, "__sip__", etd_cap) < 0) { Py_DECREF(etd_cap); Py_DECREF(enum_obj); return NULL; } Py_DECREF(etd_cap); if (etd->etd_pyslots != NULL) addTypeSlots((PyHeapTypeObject *)enum_obj, etd->etd_pyslots); return enum_obj; /* Unwind on errors. */ rel_kw_args: Py_DECREF(kw_args); rel_args: Py_DECREF(args); rel_members: Py_DECREF(members); ret_err: return NULL; } /* * Return a non-zero value if an object is a sub-class of enum.Flag. */ static int sip_api_is_enum_flag(PyObject *o) { return PyObject_IsSubclass(o, flag_type); } /* * Create a type dictionary for dynamic type being created in a module. */ static PyObject *createTypeDict(sipExportedModuleDef *em) { static PyObject *mstr = NULL; PyObject *dict; if (objectify("__module__", &mstr) < 0) return NULL; /* Create the dictionary. */ if ((dict = PyDict_New()) == NULL) return NULL; /* We need to set the module name as an attribute for dynamic types. */ if (PyDict_SetItem(dict, mstr, em->em_nameobj) < 0) { Py_DECREF(dict); return NULL; } return dict; } /* * Convert an ASCII string to a Python object if it hasn't already been done. */ static int objectify(const char *s, PyObject **objp) { if (*objp == NULL) if ((*objp = PyUnicode_FromString(s)) == NULL) return -1; return 0; } /* * Add a set of static instances to a dictionary. Note that ints are handled * separately. */ static int addInstances(PyObject *dict, sipInstancesDef *id) { if (id->id_type != NULL && addTypeInstances(dict, id->id_type) < 0) return -1; if (id->id_voidp != NULL && addVoidPtrInstances(dict,id->id_voidp) < 0) return -1; if (id->id_char != NULL && addCharInstances(dict,id->id_char) < 0) return -1; if (id->id_string != NULL && addStringInstances(dict,id->id_string) < 0) return -1; if (id->id_long != NULL && addLongInstances(dict,id->id_long) < 0) return -1; if (id->id_ulong != NULL && addUnsignedLongInstances(dict, id->id_ulong) < 0) return -1; if (id->id_llong != NULL && addLongLongInstances(dict, id->id_llong) < 0) return -1; if (id->id_ullong != NULL && addUnsignedLongLongInstances(dict, id->id_ullong) < 0) return -1; if (id->id_double != NULL && addDoubleInstances(dict,id->id_double) < 0) return -1; return 0; } /* * Get "self" from the argument tuple for a method called as * Class.Method(self, ...) rather than self.Method(...). */ static int getSelfFromArgs(sipTypeDef *td, PyObject *args, int argnr, PyObject **selfp) { PyObject *self; /* Get self from the argument tuple. */ if (argnr >= PyTuple_GET_SIZE(args)) return FALSE; self = PyTuple_GET_ITEM(args, argnr); if (!PyObject_TypeCheck(self, sipTypeAsPyTypeObject(td))) return FALSE; *selfp = self; return TRUE; } /* * Return non-zero if a method is non-lazy, ie. it must be added to the type * when it is created. */ static int isNonlazyMethod(PyMethodDef *pmd) { static const char *lazy[] = { "__getattribute__", "__getattr__", "__enter__", "__exit__", "__aenter__", "__aexit__", NULL }; const char **l; for (l = lazy; *l != NULL; ++l) if (strcmp(pmd->ml_name, *l) == 0) return TRUE; return FALSE; } /* * Add a method to a dictionary. */ static int addMethod(PyObject *dict, PyMethodDef *pmd) { PyObject *descr = sipMethodDescr_New(pmd); return dict_set_and_discard(dict, pmd->ml_name, descr); } /* * Populate a container's type dictionary. */ static int add_lazy_container_attrs(const sipTypeDef *td, sipContainerDef *cod, PyObject *dict) { int i; PyMethodDef *pmd; sipIntInstanceDef *next_int; sipVariableDef *vd; /* Do the methods. */ for (pmd = cod->cod_methods, i = 0; i < cod->cod_nrmethods; ++i, ++pmd) { /* Non-lazy methods will already have been handled. */ if (!sipTypeHasNonlazyMethod(td) || !isNonlazyMethod(pmd)) { if (addMethod(dict, pmd) < 0) return -1; } } /* Do the enums. */ next_int = cod->cod_instances.id_int; if (next_int != NULL) { sipExportedModuleDef *module = td->td_module; /* * Not ideal but we have to look through all types looking for enums * for which this container is the enclosing scope. */ for (i = 0; i < module->em_nrtypes; ++i) { sipTypeDef *enum_td = module->em_types[i]; if (enum_td != NULL && sipTypeIsEnum(enum_td)) { sipEnumTypeDef *etd = (sipEnumTypeDef *)enum_td; if (module->em_types[etd->etd_scope] == td) if (createEnum(module, etd, &next_int, dict) < 0) return -1; } } /* Do any remaining ints. */ if (addIntInstances(dict, next_int) < 0) return -1; } /* Any non-int instances. */ if (addInstances(dict, &cod->cod_instances) < 0) return -1; /* Do the variables. */ for (vd = cod->cod_variables, i = 0; i < cod->cod_nrvariables; ++i, ++vd) { PyObject *descr; if (vd->vd_type == PropertyVariable) descr = create_property(vd); else descr = sipVariableDescr_New(vd, td, cod); if (dict_set_and_discard(dict, vd->vd_name, descr) < 0) return -1; } return 0; } /* * Create a Python property object from the SIP generated structure. */ static PyObject *create_property(sipVariableDef *vd) { PyObject *descr, *fget, *fset, *fdel, *doc; descr = fget = fset = fdel = doc = NULL; if ((fget = create_function(vd->vd_getter)) == NULL) goto done; if ((fset = create_function(vd->vd_setter)) == NULL) goto done; if ((fdel = create_function(vd->vd_deleter)) == NULL) goto done; if (vd->vd_docstring == NULL) { doc = Py_None; Py_INCREF(doc); } else if ((doc = PyUnicode_FromString(vd->vd_docstring)) == NULL) { goto done; } descr = PyObject_CallFunctionObjArgs((PyObject *)&PyProperty_Type, fget, fset, fdel, doc, NULL); done: Py_XDECREF(fget); Py_XDECREF(fset); Py_XDECREF(fdel); Py_XDECREF(doc); return descr; } /* * Return a PyCFunction as an object or Py_None if there isn't one. */ static PyObject *create_function(PyMethodDef *ml) { if (ml != NULL) return PyCFunction_New(ml, NULL); Py_INCREF(Py_None); return Py_None; } /* * Populate a type dictionary with all lazy attributes if it hasn't already * been done. */ static int add_lazy_attrs(const sipTypeDef *td) { sipWrapperType *wt = (sipWrapperType *)sipTypeAsPyTypeObject(td); PyObject *dict; sipAttrGetter *ag; /* Handle the trivial case. */ if (wt->wt_dict_complete) return 0; dict = ((PyTypeObject *)wt)->tp_dict; if (sipTypeIsMapped(td)) { if (add_lazy_container_attrs(td, &((sipMappedTypeDef *)td)->mtd_container, dict) < 0) return -1; } else { sipClassTypeDef *nsx; /* Search the possible linked list of namespace extenders. */ for (nsx = (sipClassTypeDef *)td; nsx != NULL; nsx = nsx->ctd_nsextender) if (add_lazy_container_attrs((sipTypeDef *)nsx, &nsx->ctd_container, dict) < 0) return -1; } /* * Get any lazy attributes from registered getters. This must be done last * to allow any existing attributes to be replaced. */ /* * TODO: Deprecate this mechanism in favour of an event handler, or should * be be embedded code using a new directive? */ for (ag = sipAttrGetters; ag != NULL; ag = ag->next) if (ag->type == NULL || PyType_IsSubtype((PyTypeObject *)wt, ag->type)) if (ag->getter(td, dict) < 0) return -1; wt->wt_dict_complete = TRUE; PyType_Modified((PyTypeObject *)wt); return 0; } /* * Populate the type dictionary and all its super-types. */ static int add_all_lazy_attrs(const sipTypeDef *td) { if (td == NULL) return 0; if (add_lazy_attrs(td) < 0) return -1; if (sipTypeIsClass(td)) { sipClassTypeDef *ctd = (sipClassTypeDef *)td; sipEncodedTypeDef *sup; if ((sup = ctd->ctd_supers) != NULL) do { const sipTypeDef *sup_td = getGeneratedType(sup, td->td_module); if (add_all_lazy_attrs(sup_td) < 0) return -1; } while (!sup++->sc_flag); } return 0; } /* * Return the generated type structure corresponding to the given Python type * object. */ static const sipTypeDef *sip_api_type_from_py_type_object(PyTypeObject *py_type) { if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type)) return ((sipWrapperType *)py_type)->wt_td; if (PyObject_IsSubclass((PyObject *)py_type, enum_type) == 1) { PyObject *etd_cap; if ((etd_cap = PyObject_GetAttrString((PyObject *)py_type, "__sip__")) != NULL) { sipTypeDef *td = (sipTypeDef *)PyCapsule_GetPointer(etd_cap, NULL); Py_DECREF(etd_cap); return td; } PyErr_Clear(); } return NULL; } /* * Return the generated type structure corresponding to the scope of the given * type. */ static const sipTypeDef *sip_api_type_scope(const sipTypeDef *td) { if (sipTypeIsEnum(td)) { const sipEnumTypeDef *etd = (const sipEnumTypeDef *)td; if (etd->etd_scope >= 0) return td->td_module->em_types[etd->etd_scope]; } else { const sipContainerDef *cod; if (sipTypeIsMapped(td)) cod = &((const sipMappedTypeDef *)td)->mtd_container; else cod = &((const sipClassTypeDef *)td)->ctd_container; if (!cod->cod_scope.sc_flag) return getGeneratedType(&cod->cod_scope, td->td_module); } return NULL; } /* * Convert a Python object implementing an enum to an integer value. */ static int sip_api_convert_to_enum(PyObject *obj, const sipTypeDef *td) { static PyObject *value = NULL; PyObject *val_obj, *type_obj; int val; assert(sipTypeIsEnum(td)); /* Make sure the enum object has been created. */ type_obj = get_enum_type(td); /* Check the type of the Python object. */ if (PyObject_IsInstance(obj, type_obj) <= 0) { enum_expected(obj, td); return -1; } /* Get the value from the object. */ if (objectify("value", &value) < 0) return -1; if ((val_obj = PyObject_GetAttr(obj, value)) == NULL) return -1; /* Flags are implicitly unsigned. */ if (IS_UNSIGNED_ENUM((sipEnumTypeDef *)td)) val = (int)sip_api_long_as_unsigned_int(val_obj); else val = sip_api_long_as_int(val_obj); Py_DECREF(val_obj); return val; } /* * Raise an exception when failing to convert an enum because of its type. */ static void enum_expected(PyObject *obj, const sipTypeDef *td) { PyErr_Format(PyExc_TypeError, "a member of enum '%s' is expected not '%s'", sipPyNameOfEnum((sipEnumTypeDef *)td), Py_TYPE(obj)->tp_name); } /* * Create a Python object for a member of a named enum. */ static PyObject *sip_api_convert_from_enum(int eval, const sipTypeDef *td) { PyObject *et; assert(sipTypeIsEnum(td)); et = get_enum_type(td); return PyObject_CallFunction(et, IS_UNSIGNED_ENUM((sipEnumTypeDef *)td) ? "(I)" : "(i)", eval); } /* * Get the Python object for an enum type. */ static PyObject *get_enum_type(const sipTypeDef *td) { PyObject *type_obj; /* Make sure the enum object has been created. */ type_obj = (PyObject *)sipTypeAsPyTypeObject(td); if (type_obj == NULL) { if (add_all_lazy_attrs(sip_api_type_scope(td)) < 0) return NULL; type_obj = (PyObject *)sipTypeAsPyTypeObject(td); } return type_obj; } /* * Register a getter for unknown attributes. */ static int sip_api_register_attribute_getter(const sipTypeDef *td, sipAttrGetterFunc getter) { sipAttrGetter *ag = sip_api_malloc(sizeof (sipAttrGetter)); if (ag == NULL) return -1; ag->type = sipTypeAsPyTypeObject(td); ag->getter = getter; ag->next = sipAttrGetters; sipAttrGetters = ag; return 0; } /* * Register a proxy resolver. */ static int sip_api_register_proxy_resolver(const sipTypeDef *td, sipProxyResolverFunc resolver) { sipProxyResolver *pr = sip_api_malloc(sizeof (sipProxyResolver)); if (pr == NULL) return -1; pr->td = td; pr->resolver = resolver; pr->next = proxyResolvers; proxyResolvers = pr; return 0; } /* * Report a function with invalid argument types. */ static void sip_api_no_function(PyObject *parseErr, const char *func, const char *doc) { sip_api_no_method(parseErr, NULL, func, doc); } /* * Report a method/function/signal with invalid argument types. */ static void sip_api_no_method(PyObject *parseErr, const char *scope, const char *method, const char *doc) { const char *sep = "."; if (scope == NULL) scope = ++sep; if (parseErr == NULL) { /* * If we have got this far without trying a parse then there must be no * overloads. */ PyErr_Format(PyExc_TypeError, "%s%s%s() is a private method", scope, sep, method); } else if (PyList_Check(parseErr)) { PyObject *exc; /* There is an entry for each overload that was tried. */ if (PyList_GET_SIZE(parseErr) == 1) { PyObject *detail = detail_FromFailure( PyList_GET_ITEM(parseErr, 0)); if (detail != NULL) { if (doc != NULL) { PyObject *doc_obj = signature_FromDocstring(doc, 0); if (doc_obj != NULL) { exc = PyUnicode_FromFormat("%U: %U", doc_obj, detail); Py_DECREF(doc_obj); } else { exc = NULL; } } else { exc = PyUnicode_FromFormat("%s%s%s(): %U", scope, sep, method, detail); } Py_DECREF(detail); } else { exc = NULL; } } else { static const char *summary = "arguments did not match any overloaded call:"; Py_ssize_t i; if (doc != NULL) exc = PyUnicode_FromString(summary); else exc = PyUnicode_FromFormat("%s%s%s(): %s", scope, sep, method, summary); for (i = 0; i < PyList_GET_SIZE(parseErr); ++i) { PyObject *failure; PyObject *detail = detail_FromFailure( PyList_GET_ITEM(parseErr, i)); if (detail != NULL) { if (doc != NULL) { PyObject *doc_obj = signature_FromDocstring(doc, i); if (doc_obj != NULL) { failure = PyUnicode_FromFormat("\n %U: %U", doc_obj, detail); Py_DECREF(doc_obj); } else { Py_XDECREF(exc); exc = NULL; break; } } else { failure = PyUnicode_FromFormat("\n overload %zd: %U", i + 1, detail); } Py_DECREF(detail); PyUnicode_AppendAndDel(&exc, failure); } else { Py_XDECREF(exc); exc = NULL; break; } } } if (exc != NULL) { PyErr_SetObject(PyExc_TypeError, exc); Py_DECREF(exc); } } else { /* * None is used as a marker to say that an exception has already been * raised. */ assert(parseErr == Py_None); } Py_XDECREF(parseErr); } /* * Return a string/unicode object extracted from a particular line of a * docstring. */ static PyObject *signature_FromDocstring(const char *doc, Py_ssize_t line) { const char *eol; Py_ssize_t size = 0; /* * Find the start of the line. If there is a non-default versioned * overload that has been enabled then it won't have an entry in the * docstring. This means that the returned signature may be incorrect. */ while (line-- > 0) { const char *next = strchr(doc, '\n'); if (next == NULL) break; doc = next + 1; } /* Find the last closing parenthesis. */ for (eol = doc; *eol != '\n' && *eol != '\0'; ++eol) if (*eol == ')') size = eol - doc + 1; return PyUnicode_FromStringAndSize(doc, size); } /* * Return a string/unicode object that describes the given failure. */ static PyObject *detail_FromFailure(PyObject *failure_obj) { sipParseFailure *failure; PyObject *detail; failure = (sipParseFailure *)PyCapsule_GetPointer(failure_obj, NULL); switch (failure->reason) { case Unbound: detail = PyUnicode_FromFormat( "first argument of unbound method must have type '%s'", failure->detail_str); break; case TooFew: detail = PyUnicode_FromString("not enough arguments"); break; case TooMany: detail = PyUnicode_FromString("too many arguments"); break; case KeywordNotString: detail = PyUnicode_FromFormat( "%S keyword argument name is not a string", failure->detail_obj); break; case UnknownKeyword: detail = PyUnicode_FromFormat("'%U' is not a valid keyword argument", failure->detail_obj); break; case Duplicate: detail = PyUnicode_FromFormat( "'%U' has already been given as a positional argument", failure->detail_obj); break; case WrongType: if (failure->arg_nr >= 0) detail = bad_type_str(failure->arg_nr, failure->detail_obj); else detail = PyUnicode_FromFormat( "argument '%s' has unexpected type '%s'", failure->arg_name, Py_TYPE(failure->detail_obj)->tp_name); break; case Exception: detail = failure->detail_obj; if (detail) { Py_INCREF(detail); break; } /* Drop through. */ default: detail = PyUnicode_FromString("unknown reason"); } return detail; } /* * Report an abstract method called with an unbound self. */ static void sip_api_abstract_method(const char *classname, const char *method) { PyErr_Format(PyExc_TypeError, "%s.%s() is abstract and cannot be called as an unbound method", classname, method); } /* * Report a deprecated class or method. */ int sip_api_deprecated(const char *classname, const char *method) { char buf[100]; if (classname == NULL) PyOS_snprintf(buf, sizeof (buf), "%s() is deprecated", method); else if (method == NULL) PyOS_snprintf(buf, sizeof (buf), "%s constructor is deprecated", classname); else PyOS_snprintf(buf, sizeof (buf), "%s.%s() is deprecated", classname, method); return PyErr_WarnEx(PyExc_DeprecationWarning, buf, 1); } /* * Report a bad operator argument. Only a small subset of operators need to * be handled (those that don't return Py_NotImplemented). */ static void sip_api_bad_operator_arg(PyObject *self, PyObject *arg, sipPySlotType st) { const char *sn = NULL; /* Try and get the text to match a Python exception. */ switch (st) { case concat_slot: case iconcat_slot: PyErr_Format(PyExc_TypeError, "cannot concatenate '%s' and '%s' objects", Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name); break; case repeat_slot: sn = "*"; break; case irepeat_slot: sn = "*="; break; default: sn = "unknown"; } if (sn != NULL) PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %s: '%s' and '%s'", sn, Py_TYPE(self)->tp_name, Py_TYPE(arg)->tp_name); } /* * Report a sequence length that does not match the length of a slice. */ static void sip_api_bad_length_for_slice(Py_ssize_t seqlen, Py_ssize_t slicelen) { PyErr_Format(PyExc_ValueError, "attempt to assign sequence of size %zd to slice of size %zd", seqlen, slicelen); } /* * Report a Python object that cannot be converted to a particular class. */ static void sip_api_bad_class(const char *classname) { PyErr_Format(PyExc_TypeError, "cannot convert Python object to an instance of %s", classname); } /* * Report a Python member function with an unexpected result. */ static void sip_api_bad_catcher_result(PyObject *method) { PyObject *mname, *etype, *evalue, *etraceback; /* * Get the current exception object if there is one. Its string * representation will be used as the detail of a new exception. */ PyErr_Fetch(&etype, &evalue, &etraceback); PyErr_NormalizeException(&etype, &evalue, &etraceback); Py_XDECREF(etraceback); /* * This is part of the public API so we make no assumptions about the * method object. */ if (!PyMethod_Check(method) || PyMethod_GET_FUNCTION(method) == NULL || !PyFunction_Check(PyMethod_GET_FUNCTION(method)) || PyMethod_GET_SELF(method) == NULL) { PyErr_Format(PyExc_TypeError, "invalid argument to sipBadCatcherResult()"); return; } mname = ((PyFunctionObject *)PyMethod_GET_FUNCTION(method))->func_name; if (evalue != NULL) { PyErr_Format(etype, "invalid result from %s.%U(), %S", Py_TYPE(PyMethod_GET_SELF(method))->tp_name, mname, evalue); Py_DECREF(evalue); } else { PyErr_Format(PyExc_TypeError, "invalid result from %s.%U()", Py_TYPE(PyMethod_GET_SELF(method))->tp_name, mname); } Py_XDECREF(etype); } /* * Transfer ownership of a class instance to Python from C/C++. */ static void sip_api_transfer_back(PyObject *self) { if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) { sipSimpleWrapper *sw = (sipSimpleWrapper *)self; if (sipCppHasRef(sw)) { sipResetCppHasRef(sw); Py_DECREF(sw); } else { removeFromParent((sipWrapper *)sw); } sipSetPyOwned(sw); } } /* * Transfer ownership of a class instance to C/C++ from Python. */ static void sip_api_transfer_to(PyObject *self, PyObject *owner) { /* * There is a legitimate case where we try to transfer a PyObject that * may not be a SIP generated class. The virtual handler code calls * this function to keep the C/C++ instance alive when it gets rid of * the Python object returned by the Python method. A class may have * handwritten code that converts a regular Python type - so we can't * assume that we can simply cast to sipWrapper. */ if (self != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipWrapper_Type)) { sipSimpleWrapper *sw = (sipSimpleWrapper *)self; if (owner == NULL) { /* There is no owner. */ if (sipCppHasRef(sw)) { sipResetCppHasRef(sw); } else { Py_INCREF(sw); removeFromParent((sipWrapper *)sw); sipResetPyOwned(sw); } Py_DECREF(sw); } else if (owner == Py_None) { /* * The owner is a C++ instance and not a Python object (ie. there * is no parent) so there is an explicit extra reference to keep * this Python object alive. Note that there is no way to * specify this from a .sip file - it is useful when embedding in * C/C++ applications. */ if (!sipCppHasRef(sw)) { Py_INCREF(sw); removeFromParent((sipWrapper *)sw); sipResetPyOwned(sw); sipSetCppHasRef(sw); } } else if (PyObject_TypeCheck(owner, (PyTypeObject *)&sipWrapper_Type)) { /* * The owner is a Python object (ie. the C++ instance that the * Python object wraps). */ if (sipCppHasRef(sw)) { sipResetCppHasRef(sw); } else { Py_INCREF(sw); removeFromParent((sipWrapper *)sw); sipResetPyOwned(sw); } addToParent((sipWrapper *)sw, (sipWrapper *)owner); Py_DECREF(sw); } } } /* * Add a license to a dictionary. */ static int addLicense(PyObject *dict,sipLicenseDef *lc) { int rc; PyObject *ldict, *proxy, *o; /* Convert the strings we use to objects if not already done. */ if (objectify("__license__", &licenseName) < 0) return -1; if (objectify("Licensee", &licenseeName) < 0) return -1; if (objectify("Type", &typeName) < 0) return -1; if (objectify("Timestamp", ×tampName) < 0) return -1; if (objectify("Signature", &signatureName) < 0) return -1; /* We use a dictionary to hold the license information. */ if ((ldict = PyDict_New()) == NULL) return -1; /* The license type is compulsory, the rest are optional. */ if (lc->lc_type == NULL) goto deldict; if ((o = PyUnicode_FromString(lc->lc_type)) == NULL) goto deldict; rc = PyDict_SetItem(ldict,typeName,o); Py_DECREF(o); if (rc < 0) goto deldict; if (lc->lc_licensee != NULL) { if ((o = PyUnicode_FromString(lc->lc_licensee)) == NULL) goto deldict; rc = PyDict_SetItem(ldict,licenseeName,o); Py_DECREF(o); if (rc < 0) goto deldict; } if (lc->lc_timestamp != NULL) { if ((o = PyUnicode_FromString(lc->lc_timestamp)) == NULL) goto deldict; rc = PyDict_SetItem(ldict,timestampName,o); Py_DECREF(o); if (rc < 0) goto deldict; } if (lc->lc_signature != NULL) { if ((o = PyUnicode_FromString(lc->lc_signature)) == NULL) goto deldict; rc = PyDict_SetItem(ldict,signatureName,o); Py_DECREF(o); if (rc < 0) goto deldict; } /* Create a read-only proxy. */ if ((proxy = PyDictProxy_New(ldict)) == NULL) goto deldict; Py_DECREF(ldict); rc = PyDict_SetItem(dict, licenseName, proxy); Py_DECREF(proxy); return rc; deldict: Py_DECREF(ldict); return -1; } /* * Add the void pointer instances to a dictionary. */ static int addVoidPtrInstances(PyObject *dict,sipVoidPtrInstanceDef *vi) { while (vi->vi_name != NULL) { PyObject *w = sip_api_convert_from_void_ptr(vi->vi_val); if (dict_set_and_discard(dict, vi->vi_name, w) < 0) return -1; ++vi; } return 0; } /* * Add the char instances to a dictionary. */ static int addCharInstances(PyObject *dict, sipCharInstanceDef *ci) { while (ci->ci_name != NULL) { PyObject *w; switch (ci->ci_encoding) { case 'A': w = PyUnicode_DecodeASCII(&ci->ci_val, 1, NULL); break; case 'L': w = PyUnicode_DecodeLatin1(&ci->ci_val, 1, NULL); break; case '8': w = PyUnicode_FromStringAndSize(&ci->ci_val, 1); break; default: w = PyBytes_FromStringAndSize(&ci->ci_val, 1); } if (dict_set_and_discard(dict, ci->ci_name, w) < 0) return -1; ++ci; } return 0; } /* * Add the string instances to a dictionary. */ static int addStringInstances(PyObject *dict, sipStringInstanceDef *si) { while (si->si_name != NULL) { PyObject *w; switch (si->si_encoding) { case 'A': w = PyUnicode_DecodeASCII(si->si_val, strlen(si->si_val), NULL); break; case 'L': w = PyUnicode_DecodeLatin1(si->si_val, strlen(si->si_val), NULL); break; case '8': w = PyUnicode_FromString(si->si_val); break; case 'w': /* The hack for wchar_t. */ #if defined(HAVE_WCHAR_H) w = PyUnicode_FromWideChar((const wchar_t *)si->si_val, 1); break; #else raiseNoWChar(); return -1; #endif case 'W': /* The hack for wchar_t*. */ #if defined(HAVE_WCHAR_H) w = PyUnicode_FromWideChar((const wchar_t *)si->si_val, wcslen((const wchar_t *)si->si_val)); break; #else raiseNoWChar(); return -1; #endif default: w = PyBytes_FromString(si->si_val); } if (dict_set_and_discard(dict, si->si_name, w) < 0) return -1; ++si; } return 0; } /* * Add the int instances to a dictionary. */ static int addIntInstances(PyObject *dict, sipIntInstanceDef *ii) { while (ii->ii_name != NULL) { PyObject *w = PyLong_FromLong(ii->ii_val); if (dict_set_and_discard(dict, ii->ii_name, w) < 0) return -1; ++ii; } return 0; } /* * Add the long instances to a dictionary. */ static int addLongInstances(PyObject *dict,sipLongInstanceDef *li) { while (li->li_name != NULL) { PyObject *w = PyLong_FromLong(li->li_val); if (dict_set_and_discard(dict, li->li_name, w) < 0) return -1; ++li; } return 0; } /* * Add the unsigned long instances to a dictionary. */ static int addUnsignedLongInstances(PyObject *dict, sipUnsignedLongInstanceDef *uli) { while (uli->uli_name != NULL) { PyObject *w = PyLong_FromUnsignedLong(uli->uli_val); if (dict_set_and_discard(dict, uli->uli_name, w) < 0) return -1; ++uli; } return 0; } /* * Add the long long instances to a dictionary. */ static int addLongLongInstances(PyObject *dict, sipLongLongInstanceDef *lli) { while (lli->lli_name != NULL) { PyObject *w = PyLong_FromLongLong(lli->lli_val); if (dict_set_and_discard(dict, lli->lli_name, w) < 0) return -1; ++lli; } return 0; } /* * Add the unsigned long long instances to a dictionary. */ static int addUnsignedLongLongInstances(PyObject *dict, sipUnsignedLongLongInstanceDef *ulli) { while (ulli->ulli_name != NULL) { PyObject *w = PyLong_FromUnsignedLongLong(ulli->ulli_val); if (dict_set_and_discard(dict, ulli->ulli_name, w) < 0) return -1; ++ulli; } return 0; } /* * Add the double instances to a dictionary. */ static int addDoubleInstances(PyObject *dict,sipDoubleInstanceDef *di) { while (di->di_name != NULL) { PyObject *w = PyFloat_FromDouble(di->di_val); if (dict_set_and_discard(dict, di->di_name, w) < 0) return -1; ++di; } return 0; } /* * Wrap a set of type instances and add them to a dictionary. */ static int addTypeInstances(PyObject *dict, sipTypeInstanceDef *ti) { while (ti->ti_name != NULL) { if (addSingleTypeInstance(dict, ti->ti_name, ti->ti_ptr, *ti->ti_type, ti->ti_flags) < 0) return -1; ++ti; } return 0; } /* * Wrap a single type instance and add it to a dictionary. */ static int addSingleTypeInstance(PyObject *dict, const char *name, void *cppPtr, const sipTypeDef *td, int initflags) { PyObject *obj; if (sipTypeIsEnum(td)) { obj = sip_api_convert_from_enum(*(int *)cppPtr, td); } else { sipConvertFromFunc cfrom; cppPtr = resolve_proxy(td, cppPtr); cfrom = get_from_convertor(td); if (cfrom != NULL) { obj = cfrom(cppPtr, NULL); } else if (sipTypeIsMapped(td)) { raise_no_convert_from(td); return -1; } else { obj = wrap_simple_instance(cppPtr, td, NULL, initflags); } } return dict_set_and_discard(dict, name, obj); } /* * Convert a type instance and add it to a dictionary. */ static int sip_api_add_type_instance(PyObject *dict, const char *name, void *cppPtr, const sipTypeDef *td) { return addSingleTypeInstance(getDictFromObject(dict), name, cppPtr, td, 0); } /* * Return the instance dictionary for an object if it is a wrapped type. * Otherwise assume that it is a module dictionary. */ static PyObject *getDictFromObject(PyObject *obj) { if (PyObject_TypeCheck(obj, (PyTypeObject *)&sipWrapperType_Type)) obj = ((PyTypeObject *)obj)->tp_dict; return obj; } /* * Return a Python reimplementation corresponding to a C/C++ virtual function, * if any. If one was found then the GIL is acquired. This is deprecated, use * sip_api_is_python_method_12_8() instead. */ static PyObject *sip_api_is_py_method(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper *sipSelf, const char *cname, const char *mname) { return sip_api_is_py_method_12_8(gil, pymc, &sipSelf, cname, mname); } /* * Return a Python reimplementation corresponding to a C/C++ virtual function, * if any. If one was found then the GIL is acquired. */ static PyObject *sip_api_is_py_method_12_8(sip_gilstate_t *gil, char *pymc, sipSimpleWrapper **sipSelfp, const char *cname, const char *mname) { sipSimpleWrapper *sipSelf; PyObject *mname_obj, *reimp, *mro, *cls; Py_ssize_t i; /* * This is the most common case (where there is no Python reimplementation) * so we take a fast shortcut without acquiring the GIL. */ if (*pymc != 0) return NULL; /* We might still have C++ going after the interpreter has gone. */ if (sipInterpreter == NULL) return NULL; #ifdef WITH_THREAD *gil = PyGILState_Ensure(); #endif /* Only read this when we have the GIL. */ sipSelf = *sipSelfp; /* * It's possible that the Python object has been deleted but the underlying * C++ instance is still working and trying to handle virtual functions. * Alternatively, an instance has started handling virtual functions before * its ctor has returned. In either case say there is no Python * reimplementation. */ if (sipSelf != NULL) sipSelf = deref_mixin(sipSelf); if (sipSelf == NULL) goto release_gil; /* * It's possible that the object's type's tp_mro is NULL. A possible * circumstance is when a type has been created dynamically and the only * reference to it is the single instance of the type which is in the * process of being garbage collected. */ cls = (PyObject *)Py_TYPE(sipSelf); mro = ((PyTypeObject *)cls)->tp_mro; if (mro == NULL) goto release_gil; /* Get any reimplementation. */ if ((mname_obj = PyUnicode_FromString(mname)) == NULL) goto release_gil; /* * We don't use PyObject_GetAttr() because that might find the generated * C function before a reimplementation defined in a mixin (ie. later in * the MRO). However that means we must explicitly check that the class * hierarchy is fully initialised. */ if (add_all_lazy_attrs(((sipWrapperType *)Py_TYPE(sipSelf))->wt_td) < 0) { Py_DECREF(mname_obj); goto release_gil; } if (sipSelf->dict != NULL) { /* Check the instance dictionary in case it has been monkey patched. */ if ((reimp = PyDict_GetItem(sipSelf->dict, mname_obj)) != NULL && PyCallable_Check(reimp)) { Py_DECREF(mname_obj); Py_INCREF(reimp); return reimp; } } assert(PyTuple_Check(mro)); reimp = NULL; for (i = 0; i < PyTuple_GET_SIZE(mro); ++i) { PyObject *cls_dict, *cls_attr; cls = PyTuple_GET_ITEM(mro, i); cls_dict = ((PyTypeObject *)cls)->tp_dict; /* * Check any possible reimplementation is not the wrapped C++ method or * a default special method implementation. */ if (cls_dict != NULL && (cls_attr = PyDict_GetItem(cls_dict, mname_obj)) != NULL && Py_TYPE(cls_attr) != &sipMethodDescr_Type && Py_TYPE(cls_attr) != &PyWrapperDescr_Type) { reimp = cls_attr; break; } } Py_DECREF(mname_obj); if (reimp != NULL) { /* * Emulate the behaviour of a descriptor to make sure we return a bound * method. */ if (PyMethod_Check(reimp)) { /* It's already a method but make sure it is bound. */ if (PyMethod_GET_SELF(reimp) != NULL) Py_INCREF(reimp); else reimp = PyMethod_New(PyMethod_GET_FUNCTION(reimp), (PyObject *)sipSelf); } else if (PyFunction_Check(reimp)) { reimp = PyMethod_New(reimp, (PyObject *)sipSelf); } else if (Py_TYPE(reimp)->tp_descr_get) { /* It is a descriptor, so assume it will do the right thing. */ reimp = Py_TYPE(reimp)->tp_descr_get(reimp, (PyObject *)sipSelf, cls); } else { /* * We don't know what it is so just return and assume that an * appropriate exception will be raised later on. */ Py_INCREF(reimp); } } else { /* Use the fast track in future. */ *pymc = 1; if (cname != NULL) { /* Note that this will only be raised once per method. */ PyErr_Format(PyExc_NotImplementedError, "%s.%s() is abstract and must be overridden", cname, mname); PyErr_Print(); } #ifdef WITH_THREAD PyGILState_Release(*gil); #endif } return reimp; release_gil: #ifdef WITH_THREAD PyGILState_Release(*gil); #endif return NULL; } /* * Convert a C/C++ pointer to the object that wraps it. */ static PyObject *sip_api_get_pyobject(void *cppPtr, const sipTypeDef *td) { return (PyObject *)sipOMFindObject(&cppPyMap, cppPtr, td); } /* * The default access function. */ void *sip_api_get_address(sipSimpleWrapper *w) { return (w->access_func != NULL) ? w->access_func(w, GuardedPointer) : w->data; } /* * The access function for handwritten access functions. */ static void *explicit_access_func(sipSimpleWrapper *sw, AccessFuncOp op) { typedef void *(*explicitAccessFunc)(void); if (op == ReleaseGuard) return NULL; return ((explicitAccessFunc)(sw->data))(); } /* * The access function for indirect access. */ static void *indirect_access_func(sipSimpleWrapper *sw, AccessFuncOp op) { void *addr; switch (op) { case UnguardedPointer: addr = sw->data; break; case GuardedPointer: addr = *((void **)sw->data); break; default: addr = NULL; } return addr; } /* * Get the C/C++ pointer for a complex object. Note that not casting the C++ * pointer is a bug. However this would only ever be called by PyQt3 signal * emitter code and PyQt doesn't contain anything that multiply inherits from * QObject. */ static void *sip_api_get_complex_cpp_ptr(sipSimpleWrapper *sw) { return getComplexCppPtr(sw, NULL); } /* * Get the C/C++ pointer for a complex object and optionally cast it to the * required type. */ static void *getComplexCppPtr(sipSimpleWrapper *sw, const sipTypeDef *td) { if (!sipIsDerived(sw)) { PyErr_SetString(PyExc_RuntimeError, "no access to protected functions or signals for objects not created from Python"); return NULL; } return sip_api_get_cpp_ptr(sw, td); } /* * Get the C/C++ pointer from a wrapper and optionally cast it to the required * type. */ void *sip_api_get_cpp_ptr(sipSimpleWrapper *sw, const sipTypeDef *td) { void *ptr = sip_api_get_address(sw); if (checkPointer(ptr, sw) < 0) return NULL; if (td != NULL) { if (PyObject_TypeCheck((PyObject *)sw, sipTypeAsPyTypeObject(td))) ptr = cast_cpp_ptr(ptr, Py_TYPE(sw), td); else ptr = NULL; if (ptr == NULL) PyErr_Format(PyExc_TypeError, "could not convert '%s' to '%s'", Py_TYPE(sw)->tp_name, sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td)); } return ptr; } /* * Cast a C/C++ pointer from a source type to a destination type. */ static void *cast_cpp_ptr(void *ptr, PyTypeObject *src_type, const sipTypeDef *dst_type) { sipCastFunc cast = ((const sipClassTypeDef *)((sipWrapperType *)src_type)->wt_td)->ctd_cast; /* C structures and base classes don't have cast functions. */ if (cast != NULL) ptr = (*cast)(ptr, dst_type); return ptr; } /* * Check that a pointer is non-NULL. */ static int checkPointer(void *ptr, sipSimpleWrapper *sw) { if (ptr == NULL) { PyErr_Format(PyExc_RuntimeError, (sipWasCreated(sw) ? "wrapped C/C++ object of type %s has been deleted" : "super-class __init__() of type %s was never called"), Py_TYPE(sw)->tp_name); return -1; } return 0; } /* * Keep an extra reference to an object. */ static void sip_api_keep_reference(PyObject *self, int key, PyObject *obj) { PyObject *dict, *key_obj; /* * If there isn't a "self" to keep the extra reference for later garbage * collection then just take a reference and let it leak. */ if (self == NULL) { Py_XINCREF(obj); return; } /* Create the extra references dictionary if needed. */ if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL) { if ((dict = PyDict_New()) == NULL) return; ((sipSimpleWrapper *)self)->extra_refs = dict; } if ((key_obj = PyLong_FromLong(key)) != NULL) { /* This can happen if the argument was optional. */ if (obj == NULL) obj = Py_None; PyDict_SetItem(dict, key_obj, obj); Py_DECREF(key_obj); } } /* * Get an object that has an extra reference. */ static PyObject *sip_api_get_reference(PyObject *self, int key) { PyObject *dict, *key_obj, *obj; /* Get the extra references dictionary if there is one. */ if ((dict = ((sipSimpleWrapper *)self)->extra_refs) == NULL) return NULL; if ((key_obj = PyLong_FromLong(key)) == NULL) return NULL; obj = PyDict_GetItem(dict, key_obj); Py_DECREF(key_obj); Py_XINCREF(obj); return obj; } /* * Return TRUE if an object is owned by Python. Note that this isn't * implemented as a macro in sip.h because the position of the sw_flags field * is dependent on the version of Python. */ static int sip_api_is_owned_by_python(sipSimpleWrapper *sw) { return sipIsPyOwned(sw); } /* * Return TRUE if the type of a C++ instance is a derived class. Note that * this isn't implemented as a macro in sip.h because the position of the * sw_flags field is dependent on the version of Python. */ static int sip_api_is_derived_class(sipSimpleWrapper *sw) { return sipIsDerived(sw); } /* * Get the user defined object from a wrapped object. Note that this isn't * implemented as a macro in sip.h because the position of the user field is * dependent on the version of Python. */ static PyObject *sip_api_get_user_object(const sipSimpleWrapper *sw) { return sw->user; } /* * Set the user defined object in a wrapped object. Note that this isn't * implemented as a macro in sip.h because the position of the user field is * dependent on the version of Python. */ static void sip_api_set_user_object(sipSimpleWrapper *sw, PyObject *user) { sw->user = user; } /* * Check to see if a Python object can be converted to a type. */ static int sip_api_can_convert_to_type(PyObject *pyObj, const sipTypeDef *td, int flags) { int ok; assert(td == NULL || sipTypeIsClass(td) || sipTypeIsMapped(td)); if (td == NULL) { /* * The type must be /External/ and the module that contains the * implementation hasn't been imported. */ ok = FALSE; } else if (pyObj == Py_None) { /* If the type explicitly handles None then ignore the flags. */ if (sipTypeAllowNone(td)) ok = TRUE; else ok = ((flags & SIP_NOT_NONE) == 0); } else { sipConvertToFunc cto; if (sipTypeIsClass(td)) { cto = ((const sipClassTypeDef *)td)->ctd_cto; if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) ok = PyObject_TypeCheck(pyObj, sipTypeAsPyTypeObject(td)); else ok = cto(pyObj, NULL, NULL, NULL, NULL); } else { if ((cto = ((const sipMappedTypeDef *)td)->mtd_cto) != NULL) ok = cto(pyObj, NULL, NULL, NULL, NULL); else ok = FALSE; } } return ok; } /* * sip_api_convert_to_type_us() without user state support. */ static void *sip_api_convert_to_type(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp) { return sip_api_convert_to_type_us(pyObj, td, transferObj, flags, statep, NULL, iserrp); } /* * Convert a Python object to a C/C++ pointer, assuming a previous call to * sip_api_can_convert_to_type() has been successful. Allow ownership to be * transferred and any type convertors to be disabled. */ static void *sip_api_convert_to_type_us(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp) { void *cpp = NULL; int state = 0; assert(sipTypeIsClass(td) || sipTypeIsMapped(td)); /* Don't convert if there has already been an error. */ if (!*iserrp) { /* Do the conversion. */ if (pyObj == Py_None && !sipTypeAllowNone(td)) { cpp = NULL; } else { sipConvertToFunc cto; if (sipTypeIsClass(td)) { cto = ((const sipClassTypeDef *)td)->ctd_cto; if (cto == NULL || (flags & SIP_NO_CONVERTORS) != 0) { if ((cpp = sip_api_get_cpp_ptr((sipSimpleWrapper *)pyObj, td)) == NULL) { *iserrp = TRUE; } else if (transferObj != NULL) { if (transferObj == Py_None) sip_api_transfer_back(pyObj); else sip_api_transfer_to(pyObj, transferObj); } } else if (user_state_is_valid(td, user_statep)) { state = cto(pyObj, &cpp, iserrp, transferObj, user_statep); } } else if ((cto = ((const sipMappedTypeDef *)td)->mtd_cto) != NULL) { if (user_state_is_valid(td, user_statep)) state = cto(pyObj, &cpp, iserrp, transferObj, user_statep); } else { raise_no_convert_to(pyObj, td); } } } if (statep != NULL) *statep = state; return cpp; } /* * sip_api_force_convert_to_type_us() without user state support. */ static void *sip_api_force_convert_to_type(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, int *iserrp) { return sip_api_force_convert_to_type_us(pyObj, td, transferObj, flags, statep, NULL, iserrp); } /* * Convert a Python object to a C/C++ pointer and raise an exception if it * can't be done. */ void *sip_api_force_convert_to_type_us(PyObject *pyObj, const sipTypeDef *td, PyObject *transferObj, int flags, int *statep, void **user_statep, int *iserrp) { /* Don't even try if there has already been an error. */ if (*iserrp) return NULL; /* See if the object's type can be converted. */ if (!sip_api_can_convert_to_type(pyObj, td, flags)) { if (sipTypeIsMapped(td)) raise_no_convert_to(pyObj, td); else PyErr_Format(PyExc_TypeError, "%s cannot be converted to %s.%s", Py_TYPE(pyObj)->tp_name, sipNameOfModule(td->td_module), sipPyNameOfContainer(&((const sipClassTypeDef *)td)->ctd_container, td)); if (statep != NULL) *statep = 0; *iserrp = TRUE; return NULL; } /* Do the conversion. */ return sip_api_convert_to_type_us(pyObj, td, transferObj, flags, statep, user_statep, iserrp); } /* * sip_api_release_type_us() without user state support. */ static void sip_api_release_type(void *cpp, const sipTypeDef *td, int state) { sip_api_release_type_us(cpp, td, state, NULL); } /* * Release a possibly temporary C/C++ instance created by a type convertor. */ static void sip_api_release_type_us(void *cpp, const sipTypeDef *td, int state, void *user_state) { /* See if there is something to release. */ if (state & SIP_TEMPORARY) release(cpp, td, state, user_state); } /* * Release an instance. */ static void release(void *addr, const sipTypeDef *td, int state, void *user_state) { if (sipTypeIsClass(td)) { sipReleaseFunc rel = ((const sipClassTypeDef *)td)->ctd_release; /* * If there is no release function then it must be a C structure and we * can just free it. */ if (rel == NULL) sip_api_free(addr); else rel(addr, state); } else if (sipTypeIsMapped(td)) { sipReleaseUSFunc rel = ((const sipMappedTypeDef *)td)->mtd_release; if (rel != NULL) rel(addr, state, user_state); } } /* * Convert a C/C++ instance to a Python instance. */ PyObject *sip_api_convert_from_type(void *cpp, const sipTypeDef *td, PyObject *transferObj) { PyObject *py; sipConvertFromFunc cfrom; assert(sipTypeIsClass(td) || sipTypeIsMapped(td)); /* Handle None. */ if (cpp == NULL) { Py_INCREF(Py_None); return Py_None; } cpp = resolve_proxy(td, cpp); cfrom = get_from_convertor(td); if (cfrom != NULL) return cfrom(cpp, transferObj); if (sipTypeIsMapped(td)) { raise_no_convert_from(td); return NULL; } /* * See if we have already wrapped it. Invoking sub-class code can be * expensive so we check the cache first, even though the sub-class code * might perform a down-cast. */ if ((py = sip_api_get_pyobject(cpp, td)) == NULL && sipTypeHasSCC(td)) { void *orig_cpp = cpp; const sipTypeDef *orig_td = td; /* Apply the sub-class convertor. */ td = convertSubClass(td, &cpp); /* * If the sub-class convertor has done something then check the cache * again using the modified values. */ if (cpp != orig_cpp || td != orig_td) py = sip_api_get_pyobject(cpp, td); } if (py != NULL) Py_INCREF(py); else if ((py = wrap_simple_instance(cpp, td, NULL, SIP_SHARE_MAP)) == NULL) return NULL; /* Handle any ownership transfer. */ if (transferObj != NULL) { if (transferObj == Py_None) sip_api_transfer_back(py); else sip_api_transfer_to(py, transferObj); } return py; } /* * Convert a new C/C++ instance to a Python instance. */ static PyObject *sip_api_convert_from_new_type(void *cpp, const sipTypeDef *td, PyObject *transferObj) { sipWrapper *owner; sipConvertFromFunc cfrom; /* Handle None. */ if (cpp == NULL) { Py_INCREF(Py_None); return Py_None; } cpp = resolve_proxy(td, cpp); cfrom = get_from_convertor(td); if (cfrom != NULL) { PyObject *res = cfrom(cpp, transferObj); if (res != NULL) { /* * We no longer need the C/C++ instance so we release it (unless * its ownership is transferred). This means this call is * semantically equivalent to the case where we are wrapping a * class. */ if (transferObj == NULL || transferObj == Py_None) release(cpp, td, 0, NULL); } return res; } if (sipTypeIsMapped(td)) { raise_no_convert_from(td); return NULL; } /* Apply any sub-class convertor. */ if (sipTypeHasSCC(td)) td = convertSubClass(td, &cpp); /* Handle any ownership transfer. */ if (transferObj == NULL || transferObj == Py_None) owner = NULL; else owner = (sipWrapper *)transferObj; return wrap_simple_instance(cpp, td, owner, (owner == NULL ? SIP_PY_OWNED : 0)); } /* * Implement the normal transfer policy for the result of %ConvertToTypeCode, * ie. it is temporary unless it is being transferred from Python. */ int sip_api_get_state(PyObject *transferObj) { return (transferObj == NULL || transferObj == Py_None) ? SIP_TEMPORARY : 0; } /* * This is set by sip_api_find_type() before calling bsearch() on the types * table for the module. This is a hack that works around the problem of * unresolved externally defined types. */ static sipExportedModuleDef *module_searched; /* * The bsearch() helper function for searching the types table. */ static int compareTypeDef(const void *key, const void *el) { const char *s1 = (const char *)key; const char *s2 = NULL; const sipTypeDef *td; char ch1, ch2; /* Allow for unresolved externally defined types. */ td = *(const sipTypeDef **)el; if (td != NULL) { s2 = sipTypeName(td); } else { sipExternalTypeDef *etd = module_searched->em_external; assert(etd != NULL); /* Find which external type it is. */ while (etd->et_nr >= 0) { const void *tdp = &module_searched->em_types[etd->et_nr]; if (tdp == el) { s2 = etd->et_name; break; } ++etd; } assert(s2 != NULL); } /* * Compare while ignoring spaces so that we don't impose a rigorous naming * standard. This only really affects template-based mapped types. */ do { while ((ch1 = *s1++) == ' ') ; while ((ch2 = *s2++) == ' ') ; /* We might be looking for a pointer or a reference. */ if ((ch1 == '*' || ch1 == '&' || ch1 == '\0') && ch2 == '\0') return 0; } while (ch1 == ch2); return (ch1 < ch2 ? -1 : 1); } /* * Return the type structure for a particular type. */ static const sipTypeDef *sip_api_find_type(const char *type) { sipExportedModuleDef *em; for (em = moduleList; em != NULL; em = em->em_next) { sipTypeDef **tdp; /* The backdoor to the comparison helper. */ module_searched = em; tdp = (sipTypeDef **)bsearch((const void *)type, (const void *)em->em_types, em->em_nrtypes, sizeof (sipTypeDef *), compareTypeDef); if (tdp != NULL) { /* * Note that this will be NULL for unresolved externally defined * types. */ return *tdp; } } return NULL; } /* * Call a hook. */ static void sip_api_call_hook(const char *hookname) { PyObject *dictofmods, *mod, *dict, *hook, *res; /* Get the dictionary of modules. */ if ((dictofmods = PyImport_GetModuleDict()) == NULL) return; /* Get the builtins module. */ if ((mod = PyDict_GetItemString(dictofmods, "builtins")) == NULL) return; /* Get it's dictionary. */ if ((dict = PyModule_GetDict(mod)) == NULL) return; /* Get the function hook. */ if ((hook = PyDict_GetItemString(dict, hookname)) == NULL) return; /* Call the hook and discard any result. */ res = PyObject_Call(hook, empty_tuple, NULL); Py_XDECREF(res); } /* * Call any sub-class convertors for a given type returning a pointer to the * sub-type object, and possibly modifying the C++ address (in the case of * multiple inheritence). */ static const sipTypeDef *convertSubClass(const sipTypeDef *td, void **cppPtr) { /* Handle the trivial case. */ if (*cppPtr == NULL) return NULL; /* Try the conversions until told to stop. */ while (convertPass(&td, cppPtr)) ; return td; } /* * Do a single pass through the available convertors. */ static int convertPass(const sipTypeDef **tdp, void **cppPtr) { PyTypeObject *py_type = sipTypeAsPyTypeObject(*tdp); sipExportedModuleDef *em; /* * Note that this code depends on the fact that a module appears in the * list of modules before any module it imports, ie. sub-class convertors * will be invoked for more specific types first. */ for (em = moduleList; em != NULL; em = em->em_next) { sipSubClassConvertorDef *scc; if ((scc = em->em_convertors) == NULL) continue; while (scc->scc_convertor != NULL) { PyTypeObject *base_type = sipTypeAsPyTypeObject(scc->scc_basetype); /* * The base type is the "root" class that may have a number of * convertors each handling a "branch" of the derived tree of * classes. The "root" normally implements the base function that * provides the RTTI used by the convertors and is re-implemented * by derived classes. We therefore see if the target type is a * sub-class of the root, ie. see if the convertor might be able to * convert the target type to something more specific. */ if (PyType_IsSubtype(py_type, base_type)) { void *ptr; const sipTypeDef *sub_td; ptr = cast_cpp_ptr(*cppPtr, py_type, scc->scc_basetype); if ((sub_td = (*scc->scc_convertor)(&ptr)) != NULL) { PyTypeObject *sub_type = sipTypeAsPyTypeObject(sub_td); /* * We are only interested in types that are not * super-classes of the target. This happens either * because it is in an earlier convertor than the one that * handles the type or it is in a later convertor that * handles a different branch of the hierarchy. Either * way, the ordering of the modules ensures that there will * be no more than one and that it will be the right one. */ if (!PyType_IsSubtype(py_type, sub_type)) { *tdp = sub_td; *cppPtr = ptr; /* * Finally we allow the convertor to return a type that * is apparently unrelated to the current convertor. * This causes the whole process to be restarted with * the new values. The use case is PyQt's QLayoutItem. */ return !PyType_IsSubtype(sub_type, base_type); } } } ++scc; } } /* * We haven't found the exact type, so return the most specific type that * it must be. This can happen legitimately if the wrapped library is * returning an internal class that is down-cast to a more generic class. * Also we want this function to be safe when a class doesn't have any * convertors. */ return FALSE; } /* * Raise an unknown exception. Make no assumptions about the GIL. */ static void sip_api_raise_unknown_exception(void) { static PyObject *mobj = NULL; SIP_BLOCK_THREADS objectify("unknown", &mobj); PyErr_SetObject(PyExc_Exception, mobj); SIP_UNBLOCK_THREADS } /* * Raise an exception implemented as a type. Make no assumptions about the * GIL. */ static void sip_api_raise_type_exception(const sipTypeDef *td, void *ptr) { PyObject *self; assert(sipTypeIsClass(td)); SIP_BLOCK_THREADS self = wrap_simple_instance(ptr, td, NULL, SIP_PY_OWNED); PyErr_SetObject((PyObject *)sipTypeAsPyTypeObject(td), self); Py_XDECREF(self); SIP_UNBLOCK_THREADS } /* * Return the generated type structure of an encoded type. */ static sipTypeDef *getGeneratedType(const sipEncodedTypeDef *enc, sipExportedModuleDef *em) { if (enc->sc_module == 255) return em->em_types[enc->sc_type]; return em->em_imports[enc->sc_module].im_imported_types[enc->sc_type].it_td; } /* * Return the generated class type structure of a class's super-class. */ sipClassTypeDef *sipGetGeneratedClassType(const sipEncodedTypeDef *enc, const sipClassTypeDef *ctd) { return (sipClassTypeDef *)getGeneratedType(enc, ctd->ctd_base.td_module); } /* * Find a particular slot function for a type. */ static void *findSlot(PyObject *self, sipPySlotType st) { void *slot = NULL; PyTypeObject *py_type = Py_TYPE(self); /* See if it is a wrapper. */ /* TODO: will this always be TRUE? */ if (PyObject_TypeCheck((PyObject *)py_type, &sipWrapperType_Type)) { const sipClassTypeDef *ctd; ctd = (sipClassTypeDef *)((sipWrapperType *)(py_type))->wt_td; slot = findSlotInClass(ctd, st); } return slot; } /* * Find a particular slot function in a class hierarchy. */ static void *findSlotInClass(const sipClassTypeDef *ctd, sipPySlotType st) { void *slot; if (ctd->ctd_pyslots != NULL) slot = findSlotInSlotList(ctd->ctd_pyslots, st); else slot = NULL; if (slot == NULL) { sipEncodedTypeDef *sup; /* Search any super-types. */ if ((sup = ctd->ctd_supers) != NULL) { do { const sipClassTypeDef *sup_ctd = sipGetGeneratedClassType( sup, ctd); slot = findSlotInClass(sup_ctd, st); } while (slot == NULL && !sup++->sc_flag); } } return slot; } /* * Find a particular slot function in a particular type. */ static void *findSlotInSlotList(sipPySlotDef *psd, sipPySlotType st) { while (psd->psd_func != NULL) { if (psd->psd_type == st) return psd->psd_func; ++psd; } return NULL; } /* * Return the C/C++ address and the generated class structure for a wrapper. */ static void *getPtrTypeDef(sipSimpleWrapper *self, const sipClassTypeDef **ctd) { *ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(self))->wt_td; return (sipNotInMap(self) ? NULL : sip_api_get_address(self)); } /* * Handle an objobjargproc slot. */ static int objobjargprocSlot(PyObject *self, PyObject *arg1, PyObject *arg2, sipPySlotType st) { int (*f)(PyObject *, PyObject *); int res; f = (int (*)(PyObject *, PyObject *))findSlot(self, st); if (f != NULL) { PyObject *args; /* * Slot handlers require a single PyObject *. The second argument is * optional. */ if (arg2 == NULL) { args = arg1; Py_INCREF(args); } else if ((args = PyTuple_Pack(2, arg1, arg2)) == NULL) { return -1; } res = f(self, args); Py_DECREF(args); } else { PyErr_SetNone(PyExc_NotImplementedError); res = -1; } return res; } /* * Handle an ssizeobjargproc slot. */ static int ssizeobjargprocSlot(PyObject *self, Py_ssize_t arg1, PyObject *arg2, sipPySlotType st) { int (*f)(PyObject *, PyObject *); int res; f = (int (*)(PyObject *, PyObject *))findSlot(self, st); if (f != NULL) { PyObject *args; /* * Slot handlers require a single PyObject *. The second argument is * optional. */ if (arg2 == NULL) args = PyLong_FromSsize_t(arg1); else args = Py_BuildValue("(nO)", arg1, arg2); if (args == NULL) return -1; res = f(self, args); Py_DECREF(args); } else { PyErr_SetNone(PyExc_NotImplementedError); res = -1; } return res; } /* * The metatype alloc slot. */ static PyObject *sipWrapperType_alloc(PyTypeObject *self, Py_ssize_t nitems) { PyObject *o; /* Call the standard super-metatype alloc. */ if ((o = PyType_Type.tp_alloc(self, nitems)) == NULL) return NULL; /* * Consume any extra type specific information and use it to initialise the * slots. This only happens for directly wrapped classes (and not * programmer written sub-classes). This must be done in the alloc * function because it is the only place we can break out of the default * new() function before PyType_Ready() is called. */ if (currentType != NULL) { assert(!sipTypeIsEnum(currentType)); ((sipWrapperType *)o)->wt_td = currentType; if (sipTypeIsClass(currentType)) { const sipClassTypeDef *ctd = (const sipClassTypeDef *)currentType; const char *docstring = ctd->ctd_docstring; /* * Skip the marker that identifies the docstring as being * automatically generated. */ if (docstring != NULL && *docstring == AUTO_DOCSTRING) ++docstring; ((PyTypeObject *)o)->tp_doc = docstring; addClassSlots((sipWrapperType *)o, ctd); /* Patch any mixin initialiser. */ if (ctd->ctd_init_mixin != NULL) ((PyTypeObject *)o)->tp_init = ctd->ctd_init_mixin; } } return o; } /* * The metatype init slot. */ static int sipWrapperType_init(sipWrapperType *self, PyObject *args, PyObject *kwds) { /* Call the standard super-metatype init. */ if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) return -1; /* * If we don't yet have any extra type specific information (because we are * a programmer defined sub-class) then get it from the (first) super-type. */ if (self->wt_td == NULL) { PyTypeObject *base = ((PyTypeObject *)self)->tp_base; self->wt_user_type = TRUE; /* * We allow the class to use this as a meta-type without being derived * from a class that uses it. This allows mixin classes that need * their own meta-type to work so long as their meta-type is derived * from this meta-type. This condition is indicated by the pointer to * the generated type structure being NULL. */ if (base != NULL && PyObject_TypeCheck((PyObject *)base, (PyTypeObject *)&sipWrapperType_Type)) self->wt_td = ((sipWrapperType *)base)->wt_td; } else { /* * We must be a generated type so remember the type object in the * generated type structure. */ assert(self->wt_td->td_py_type == NULL); self->wt_td->td_py_type = (PyTypeObject *)self; } return 0; } /* * The metatype getattro slot. */ static PyObject *sipWrapperType_getattro(PyObject *self, PyObject *name) { if (add_all_lazy_attrs(((sipWrapperType *)self)->wt_td) < 0) return NULL; return PyType_Type.tp_getattro(self, name); } /* * The metatype setattro slot. */ static int sipWrapperType_setattro(PyObject *self, PyObject *name, PyObject *value) { if (add_all_lazy_attrs(((sipWrapperType *)self)->wt_td) < 0) return -1; return PyType_Type.tp_setattro(self, name, value); } /* * The instance new slot. */ static PyObject *sipSimpleWrapper_new(sipWrapperType *wt, PyObject *args, PyObject *kwds) { sipTypeDef *td = wt->wt_td; (void)args; (void)kwds; /* Check the base types are not being used directly. */ if (wt == &sipSimpleWrapper_Type || wt == &sipWrapper_Type) { PyErr_Format(PyExc_TypeError, "the %s type cannot be instantiated or sub-classed", ((PyTypeObject *)wt)->tp_name); return NULL; } if (add_all_lazy_attrs(td) < 0) return NULL; /* See if it is a mapped type. */ if (sipTypeIsMapped(td)) { PyErr_Format(PyExc_TypeError, "%s.%s represents a mapped type and cannot be instantiated", sipNameOfModule(td->td_module), sipPyNameOfContainer(get_container(td), td)); return NULL; } /* See if it is a namespace. */ if (sipTypeIsNamespace(td)) { PyErr_Format(PyExc_TypeError, "%s.%s represents a C++ namespace and cannot be instantiated", sipNameOfModule(td->td_module), sipPyNameOfContainer(get_container(td), td)); return NULL; } /* * See if the object is being created explicitly rather than being wrapped. */ if (!sipIsPending()) { /* * See if it cannot be instantiated or sub-classed from Python, eg. * it's an opaque class. Some restrictions might be overcome with * better SIP support. */ if (((sipClassTypeDef *)td)->ctd_init == NULL) { PyErr_Format(PyExc_TypeError, "%s.%s cannot be instantiated or sub-classed", sipNameOfModule(td->td_module), sipPyNameOfContainer(get_container(td), td)); return NULL; } /* See if it is an abstract type. */ if (sipTypeIsAbstract(td) && !wt->wt_user_type && ((sipClassTypeDef *)td)->ctd_init_mixin == NULL) { PyErr_Format(PyExc_TypeError, "%s.%s represents a C++ abstract class and cannot be instantiated", sipNameOfModule(td->td_module), sipPyNameOfContainer(get_container(td), td)); return NULL; } } /* Call the standard super-type new. */ return PyBaseObject_Type.tp_new((PyTypeObject *)wt, empty_tuple, NULL); } /* * The instance init slot. */ static int sipSimpleWrapper_init(sipSimpleWrapper *self, PyObject *args, PyObject *kwds) { void *sipNew; int sipFlags, from_cpp = TRUE; sipWrapper *owner; sipWrapperType *wt = (sipWrapperType *)Py_TYPE(self); sipTypeDef *td = wt->wt_td; sipClassTypeDef *ctd = (sipClassTypeDef *)td; PyObject *unused = NULL; sipFinalFunc final_func = find_finalisation(ctd); /* Check for an existing C++ instance waiting to be wrapped. */ if (sipGetPending(&sipNew, &owner, &sipFlags) < 0) return -1; if (sipNew == NULL) { PyObject *parseErr = NULL, **unused_p = NULL; /* See if we are interested in any unused keyword arguments. */ if (sipTypeCallSuperInit(&ctd->ctd_base) || final_func != NULL) unused_p = &unused; /* Call the C++ ctor. */ owner = NULL; sipNew = ctd->ctd_init(self, args, kwds, unused_p, (PyObject **)&owner, &parseErr); if (sipNew != NULL) { sipFlags = SIP_DERIVED_CLASS; } else if (parseErr == NULL) { /* * The C++ ctor must have raised an exception which has been * translated to a Python exception. */ return -1; } else { sipInitExtenderDef *ie = wt->wt_iextend; /* * If we have not found an appropriate overload then try any * extenders. */ while (PyList_Check(parseErr) && ie != NULL) { sipNew = ie->ie_extender(self, args, kwds, &unused, (PyObject **)&owner, &parseErr); if (sipNew != NULL) break; ie = ie->ie_next; } if (sipNew == NULL) { const char *docstring = ctd->ctd_docstring; /* * Use the docstring for errors if it was automatically * generated. */ if (docstring != NULL) { if (*docstring == AUTO_DOCSTRING) ++docstring; else docstring = NULL; } sip_api_no_function(parseErr, sipPyNameOfContainer(&ctd->ctd_container, td), docstring); return -1; } sipFlags = 0; } if (owner == NULL) sipFlags |= SIP_PY_OWNED; else if ((PyObject *)owner == Py_None) { /* This is the hack that means that C++ owns the new instance. */ sipFlags |= SIP_CPP_HAS_REF; Py_INCREF(self); owner = NULL; } /* The instance was created from Python. */ from_cpp = FALSE; } /* Handler any owner if the type supports the concept. */ if (PyObject_TypeCheck((PyObject *)self, (PyTypeObject *)&sipWrapper_Type)) { /* * The application may be doing something very unadvisable (like * calling __init__() for a second time), so make sure we don't already * have a parent. */ removeFromParent((sipWrapper *)self); if (owner != NULL) { assert(PyObject_TypeCheck((PyObject *)owner, (PyTypeObject *)&sipWrapper_Type)); addToParent((sipWrapper *)self, (sipWrapper *)owner); } } self->data = sipNew; self->sw_flags = sipFlags | SIP_CREATED; /* Set the access function. */ if (sipIsAccessFunc(self)) self->access_func = explicit_access_func; else if (sipIsIndirect(self)) self->access_func = indirect_access_func; else self->access_func = NULL; if (!sipNotInMap(self)) sipOMAddObject(&cppPyMap, self); /* If we are wrapping an instance returned from C/C++ then we are done. */ if (from_cpp) { /* * Invoke any event handlers for instances that are accessed directly. */ if (self->access_func == NULL) { sipEventHandler *eh; for (eh = event_handlers[sipEventWrappedInstance]; eh != NULL; eh = eh->next) { if (is_subtype(ctd, eh->ctd)) { sipWrappedInstanceEventHandler handler = (sipWrappedInstanceEventHandler)eh->handler; handler(sipNew); } } } return 0; } /* Call any finalisation code. */ if (final_func != NULL) { PyObject *new_unused = NULL, **new_unused_p; if (unused == NULL || unused != kwds) { /* * There are no unused arguments or we have already created a dict * containing the unused sub-set, so there is no need to create * another. */ new_unused_p = NULL; } else { /* * All of the keyword arguments are unused, so if some of them are * now going to be used then a new dict will be needed. */ new_unused_p = &new_unused; } if (final_func((PyObject *)self, sipNew, unused, new_unused_p) < 0) { Py_XDECREF(unused); return -1; } if (new_unused != NULL) { Py_DECREF(unused); unused = new_unused; } } /* See if we should call the equivalent of super().__init__(). */ if (sipTypeCallSuperInit(&ctd->ctd_base)) { PyObject *next; /* Find the next type in the MRO. */ next = next_in_mro((PyObject *)self, (PyObject *)&sipSimpleWrapper_Type); /* * If the next type in the MRO is object then take a shortcut by not * calling super().__init__() but emulating object.__init__() instead. * This will be the most common case and also allows us to generate a * better exception message if there are unused keyword arguments. The * disadvantage is that the exception message will be different if * there is a mixin. */ if (next != (PyObject *)&PyBaseObject_Type) { int rc = super_init((PyObject *)self, empty_tuple, unused, next); Py_XDECREF(unused); return rc; } } if (unused_backdoor != NULL) { /* * We are being called by a mixin's __init__ so save any unused * arguments for it to pass on to the main class's __init__. */ *unused_backdoor = unused; } else if (unused != NULL) { /* We shouldn't have any unused keyword arguments. */ if (PyDict_Size(unused) != 0) { PyObject *key, *value; Py_ssize_t pos = 0; /* Just report one of the unused arguments. */ PyDict_Next(unused, &pos, &key, &value); PyErr_Format(PyExc_TypeError, "'%S' is an unknown keyword argument", key); Py_DECREF(unused); return -1; } Py_DECREF(unused); } return 0; } /* * Get the C++ address of a mixin. */ static void *sip_api_get_mixin_address(sipSimpleWrapper *w, const sipTypeDef *td) { PyObject *mixin; void *cpp; if ((mixin = PyObject_GetAttrString((PyObject *)w, sipTypeName(td))) == NULL) { PyErr_Clear(); return NULL; } cpp = sip_api_get_address((sipSimpleWrapper *)mixin); Py_DECREF(mixin); return cpp; } /* * Initialise a mixin. */ static int sip_api_init_mixin(PyObject *self, PyObject *args, PyObject *kwds, const sipClassTypeDef *ctd) { int rc; Py_ssize_t pos; PyObject *unused, *mixin, *mixin_name, *key, *value; PyTypeObject *self_wt = sipTypeAsPyTypeObject(((sipWrapperType *)Py_TYPE(self))->wt_td); PyTypeObject *wt = sipTypeAsPyTypeObject(&ctd->ctd_base); static PyObject *double_us = NULL; if (objectify("__", &double_us) < 0) return -1; /* If we are not a mixin to another wrapped class then behave as normal. */ if (PyType_IsSubtype(self_wt, wt)) return super_init(self, args, kwds, next_in_mro(self, (PyObject *)wt)); /* * Create the mixin instance. Retain the positional arguments for the * super-class. Remember that, even though the mixin appears after the * main class in the MRO, it appears before sipWrapperType where the main * class's arguments are actually parsed. */ unused = NULL; unused_backdoor = &unused; mixin = PyObject_Call((PyObject *)wt, empty_tuple, kwds); unused_backdoor = NULL; if (mixin == NULL) goto gc_unused; /* Make sure the mixin can find the main instance. */ ((sipSimpleWrapper *)mixin)->mixin_main = self; Py_INCREF(self); if ((mixin_name = PyUnicode_FromString(sipTypeName(&ctd->ctd_base))) == NULL) { Py_DECREF(mixin); goto gc_unused; } rc = PyObject_SetAttr(self, mixin_name, mixin); Py_DECREF(mixin); if (rc < 0) goto gc_mixin_name; /* Add the mixin's useful attributes to the main class. */ pos = 0; while (PyDict_Next(wt->tp_dict, &pos, &key, &value)) { /* Don't replace existing values. */ if (PyDict_Contains(Py_TYPE(self)->tp_dict, key) != 0) continue; /* Skip values with names that start with double underscore. */ if (!PyUnicode_Check(key)) continue; /* * Despite what the docs say this returns a Py_ssize_t - although the * docs are probably right. */ rc = (int)PyUnicode_Tailmatch(key, double_us, 0, 2, -1); if (rc < 0) goto gc_mixin_name; if (rc > 0) continue; if (PyObject_IsInstance(value, (PyObject *)&sipMethodDescr_Type)) { if ((value = sipMethodDescr_Copy(value, mixin_name)) == NULL) goto gc_mixin_name; } else if (PyObject_IsInstance(value, (PyObject *)&sipVariableDescr_Type)) { if ((value = sipVariableDescr_Copy(value, mixin_name)) == NULL) goto gc_mixin_name; } else { Py_INCREF(value); } rc = PyDict_SetItem(Py_TYPE(self)->tp_dict, key, value); Py_DECREF(value); if (rc < 0) goto gc_mixin_name; } Py_DECREF(mixin_name); /* Call the super-class's __init__ with any remaining arguments. */ rc = super_init(self, args, unused, next_in_mro(self, (PyObject *)wt)); Py_XDECREF(unused); return rc; gc_mixin_name: Py_DECREF(mixin_name); gc_unused: Py_XDECREF(unused); return -1; } /* * Return the next in the MRO of an instance after a given type. */ static PyObject *next_in_mro(PyObject *self, PyObject *after) { Py_ssize_t i; PyObject *mro; mro = Py_TYPE(self)->tp_mro; assert(PyTuple_Check(mro)); for (i = 0; i < PyTuple_GET_SIZE(mro); ++i) if (PyTuple_GET_ITEM(mro, i) == after) break; /* Assert that we have found ourself and that we are not the last. */ assert(i + 1 < PyTuple_GET_SIZE(mro)); return PyTuple_GET_ITEM(mro, i + 1); } /* * Call the equivalent of super()__init__() of an instance. */ static int super_init(PyObject *self, PyObject *args, PyObject *kwds, PyObject *type) { int i; PyObject *init, *init_args, *init_res; if ((init = PyObject_GetAttr(type, init_name)) == NULL) return -1; if ((init_args = PyTuple_New(1 + PyTuple_GET_SIZE(args))) == NULL) { Py_DECREF(init); return -1; } PyTuple_SET_ITEM(init_args, 0, self); Py_INCREF(self); for (i = 0; i < PyTuple_GET_SIZE(args); ++i) { PyObject *arg = PyTuple_GET_ITEM(args, i); PyTuple_SET_ITEM(init_args, 1 + i, arg); Py_INCREF(arg); } init_res = PyObject_Call(init, init_args, kwds); Py_DECREF(init_args); Py_DECREF(init); Py_XDECREF(init_res); return (init_res != NULL) ? 0 : -1; } /* * Find any finalisation function for a class, searching its super-classes if * necessary. */ static sipFinalFunc find_finalisation(sipClassTypeDef *ctd) { sipEncodedTypeDef *sup; if (ctd->ctd_final != NULL) return ctd->ctd_final; if ((sup = ctd->ctd_supers) != NULL) do { sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); sipFinalFunc func; if ((func = find_finalisation(sup_ctd)) != NULL) return func; } while (!sup++->sc_flag); return NULL; } /* * The instance traverse slot. */ static int sipSimpleWrapper_traverse(sipSimpleWrapper *self, visitproc visit, void *arg) { int vret; void *ptr; const sipClassTypeDef *ctd; /* Call any handwritten traverse code. */ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) if (ctd->ctd_traverse != NULL) if ((vret = ctd->ctd_traverse(ptr, visit, arg)) != 0) return vret; if (self->dict != NULL) if ((vret = visit(self->dict, arg)) != 0) return vret; if (self->extra_refs != NULL) if ((vret = visit(self->extra_refs, arg)) != 0) return vret; if (self->user != NULL) if ((vret = visit(self->user, arg)) != 0) return vret; if (self->mixin_main != NULL) if ((vret = visit(self->mixin_main, arg)) != 0) return vret; return 0; } /* * The instance clear slot. */ static int sipSimpleWrapper_clear(sipSimpleWrapper *self) { int vret = 0; void *ptr; const sipClassTypeDef *ctd; PyObject *tmp; /* Call any handwritten clear code. */ if ((ptr = getPtrTypeDef(self, &ctd)) != NULL) if (ctd->ctd_clear != NULL) vret = ctd->ctd_clear(ptr); /* Remove the instance dictionary. */ tmp = self->dict; self->dict = NULL; Py_XDECREF(tmp); /* Remove any extra references dictionary. */ tmp = self->extra_refs; self->extra_refs = NULL; Py_XDECREF(tmp); /* Remove any user object. */ tmp = self->user; self->user = NULL; Py_XDECREF(tmp); /* Remove any mixin main. */ tmp = self->mixin_main; self->mixin_main = NULL; Py_XDECREF(tmp); return vret; } /* * The instance get buffer slot. */ static int sipSimpleWrapper_getbuffer(sipSimpleWrapper *self, Py_buffer *buf, int flags) { void *ptr; const sipClassTypeDef *ctd; if ((ptr = getPtrTypeDef(self, &ctd)) == NULL) return -1; if (sipTypeUseLimitedAPI(&ctd->ctd_base)) { sipGetBufferFuncLimited getbuffer = (sipGetBufferFuncLimited)ctd->ctd_getbuffer; sipBufferDef bd; /* * Ensure all fields have a default value. This means that extra * fields can be appended in the future that older handwritten code * doesn't know about. */ memset(&bd, 0, sizeof(sipBufferDef)); if (getbuffer((PyObject *)self, ptr, &bd) < 0) return -1; return PyBuffer_FillInfo(buf, (PyObject *)self, bd.bd_buffer, bd.bd_length, bd.bd_readonly, flags); } return ctd->ctd_getbuffer((PyObject *)self, ptr, buf, flags); } /* * The instance release buffer slot. */ static void sipSimpleWrapper_releasebuffer(sipSimpleWrapper *self, Py_buffer *buf) { void *ptr; const sipClassTypeDef *ctd; if ((ptr = getPtrTypeDef(self, &ctd)) == NULL) return; if (sipTypeUseLimitedAPI(&ctd->ctd_base)) { sipReleaseBufferFuncLimited releasebuffer = (sipReleaseBufferFuncLimited)ctd->ctd_releasebuffer; releasebuffer((PyObject *)self, ptr); return; } ctd->ctd_releasebuffer((PyObject *)self, ptr, buf); } /* * The instance dealloc slot. */ static void sipSimpleWrapper_dealloc(sipSimpleWrapper *self) { PyObject *error_type, *error_value, *error_traceback; /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); forgetObject(self); /* * Now that the C++ object no longer exists we can tidy up the Python * object. We used to do this first but that meant lambda slots were * removed too soon (if they were connected to QObject.destroyed()). */ sipSimpleWrapper_clear(self); /* Call the standard super-type dealloc. */ PyBaseObject_Type.tp_dealloc((PyObject *)self); /* Restore the saved exception. */ PyErr_Restore(error_type, error_value, error_traceback); } /* * The type call slot. */ static PyObject *slot_call(PyObject *self, PyObject *args, PyObject *kw) { PyObject *(*f)(PyObject *, PyObject *, PyObject *); f = (PyObject *(*)(PyObject *, PyObject *, PyObject *))findSlot(self, call_slot); assert(f != NULL); return f(self, args, kw); } /* * The sequence type item slot. */ static PyObject *slot_sq_item(PyObject *self, Py_ssize_t n) { PyObject *(*f)(PyObject *,PyObject *); PyObject *arg, *res; if ((arg = PyLong_FromSsize_t(n)) == NULL) return NULL; f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, getitem_slot); assert(f != NULL); res = f(self,arg); Py_DECREF(arg); return res; } /* * The mapping type assign subscript slot. */ static int slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { return objobjargprocSlot(self, key, value, (value != NULL ? setitem_slot : delitem_slot)); } /* * The sequence type assign item slot. */ static int slot_sq_ass_item(PyObject *self, Py_ssize_t i, PyObject *o) { return ssizeobjargprocSlot(self, i, o, (o != NULL ? setitem_slot : delitem_slot)); } /* * The type rich compare slot. */ static PyObject *slot_richcompare(PyObject *self, PyObject *arg, int op) { PyObject *(*f)(PyObject *,PyObject *); sipPySlotType st; /* Convert the operation to a slot type. */ switch (op) { case Py_LT: st = lt_slot; break; case Py_LE: st = le_slot; break; case Py_EQ: st = eq_slot; break; case Py_NE: st = ne_slot; break; case Py_GT: st = gt_slot; break; case Py_GE: st = ge_slot; break; } /* It might not exist if not all the above have been implemented. */ if ((f = (PyObject *(*)(PyObject *,PyObject *))findSlot(self, st)) == NULL) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return f(self, arg); } /* * The __dict__ getter. */ static PyObject *sipSimpleWrapper_get_dict(sipSimpleWrapper *sw, void *closure) { (void)closure; /* Create the dictionary if needed. */ if (sw->dict == NULL) { sw->dict = PyDict_New(); if (sw->dict == NULL) return NULL; } Py_INCREF(sw->dict); return sw->dict; } /* * The __dict__ setter. */ static int sipSimpleWrapper_set_dict(sipSimpleWrapper *sw, PyObject *value, void *closure) { (void)closure; /* Check that any new value really is a dictionary. */ if (value != NULL && !PyDict_Check(value)) { PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%s'", Py_TYPE(value)->tp_name); return -1; } Py_XDECREF(sw->dict); Py_XINCREF(value); sw->dict = value; return 0; } /* * The table of getters and setters. */ static PyGetSetDef sipSimpleWrapper_getset[] = { {(char *)"__dict__", (getter)sipSimpleWrapper_get_dict, (setter)sipSimpleWrapper_set_dict, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL} }; /* * The type data structure. Note that we pretend to be a mapping object and a * sequence object at the same time. Python will choose one over another, * depending on the context, but we implement as much as we can and don't make * assumptions about which Python will choose. */ sipWrapperType sipSimpleWrapper_Type = { #if !defined(STACKLESS) { #endif { PyVarObject_HEAD_INIT(&sipWrapperType_Type, 0) _SIP_MODULE_FQ_NAME ".simplewrapper", /* tp_name */ sizeof (sipSimpleWrapper), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)sipSimpleWrapper_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)sipSimpleWrapper_traverse, /* tp_traverse */ (inquiry)sipSimpleWrapper_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ sipSimpleWrapper_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(sipSimpleWrapper, dict), /* tp_dictoffset */ (initproc)sipSimpleWrapper_init, /* tp_init */ 0, /* tp_alloc */ (newfunc)sipSimpleWrapper_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }, { 0, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ }, { 0, /* nb_add */ 0, /* nb_subtract */ 0, /* nb_multiply */ 0, /* nb_remainder */ 0, /* nb_divmod */ 0, /* nb_power */ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ 0, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ 0, /* nb_int */ 0, /* nb_reserved */ 0, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ 0, /* nb_floor_divide */ 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ 0, /* nb_matrix_multiply */ 0, /* nb_inplace_matrix_multiply */ }, { 0, /* mp_length */ 0, /* mp_subscript */ 0, /* mp_ass_subscript */ }, { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* was_sq_slice */ 0, /* sq_ass_item */ 0, /* was_sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }, { 0, /* bf_getbuffer */ 0, /* bf_releasebuffer */ }, 0, /* ht_name */ 0, /* ht_slots */ 0, /* ht_qualname */ 0, /* ht_cached_keys */ #if PY_VERSION_HEX >= 0x03090000 0, /* ht_module */ #endif #if !defined(STACKLESS) }, #endif 0, /* wt_user_type */ 0, /* wt_dict_complete */ 0, /* wt_unused */ 0, /* wt_td */ 0, /* wt_iextend */ 0, /* wt_user_data */ }; /* * The wrapper clear slot. */ static int sipWrapper_clear(sipWrapper *self) { int vret; sipSimpleWrapper *sw = (sipSimpleWrapper *)self; vret = sipSimpleWrapper_clear(sw); /* Detach any children (which will be owned by C/C++). */ detachChildren(self); return vret; } /* * The wrapper dealloc slot. */ static void sipWrapper_dealloc(sipWrapper *self) { PyObject *error_type, *error_value, *error_traceback; /* Save the current exception, if any. */ PyErr_Fetch(&error_type, &error_value, &error_traceback); /* * We can't simply call the super-type because things have to be done in a * certain order. The first thing is to get rid of the wrapped instance. */ forgetObject((sipSimpleWrapper *)self); sipWrapper_clear(self); /* Skip the super-type's dealloc. */ PyBaseObject_Type.tp_dealloc((PyObject *)self); /* Restore the saved exception. */ PyErr_Restore(error_type, error_value, error_traceback); } /* * The wrapper traverse slot. */ static int sipWrapper_traverse(sipWrapper *self, visitproc visit, void *arg) { int vret; sipSimpleWrapper *sw = (sipSimpleWrapper *)self; sipWrapper *w; if ((vret = sipSimpleWrapper_traverse(sw, visit, arg)) != 0) return vret; for (w = self->first_child; w != NULL; w = w->sibling_next) { /* * We don't traverse if the wrapper is a child of itself. We do this * so that wrapped objects returned by virtual methods with the * /Factory/ don't have those objects collected. This then means that * plugins implemented in Python have a chance of working. */ if (w != self) if ((vret = visit((PyObject *)w, arg)) != 0) return vret; } return 0; } /* * Add the slots for a class type and all its super-types. */ static void addClassSlots(sipWrapperType *wt, const sipClassTypeDef *ctd) { PyHeapTypeObject *heap_to = &wt->super; PyBufferProcs *bp = &heap_to->as_buffer; /* Add the buffer interface. */ if (ctd->ctd_getbuffer != NULL) bp->bf_getbuffer = (getbufferproc)sipSimpleWrapper_getbuffer; if (ctd->ctd_releasebuffer != NULL) bp->bf_releasebuffer = (releasebufferproc)sipSimpleWrapper_releasebuffer; /* Add the slots for this type. */ if (ctd->ctd_pyslots != NULL) addTypeSlots(heap_to, ctd->ctd_pyslots); } /* * Add the slot handler for each slot present in the type. */ static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots) { PyTypeObject *to; PyNumberMethods *nb; PySequenceMethods *sq; PyMappingMethods *mp; PyAsyncMethods *am; void *f; to = &heap_to->ht_type; nb = &heap_to->as_number; sq = &heap_to->as_sequence; mp = &heap_to->as_mapping; am = &heap_to->as_async; while ((f = slots->psd_func) != NULL) switch (slots++->psd_type) { case str_slot: to->tp_str = (reprfunc)f; break; case int_slot: nb->nb_int = (unaryfunc)f; break; case float_slot: nb->nb_float = (unaryfunc)f; break; case len_slot: mp->mp_length = (lenfunc)f; sq->sq_length = (lenfunc)f; break; case contains_slot: sq->sq_contains = (objobjproc)f; break; case add_slot: nb->nb_add = (binaryfunc)f; break; case concat_slot: sq->sq_concat = (binaryfunc)f; break; case sub_slot: nb->nb_subtract = (binaryfunc)f; break; case mul_slot: nb->nb_multiply = (binaryfunc)f; break; case repeat_slot: sq->sq_repeat = (ssizeargfunc)f; break; case div_slot: nb->nb_true_divide = (binaryfunc)f; break; case mod_slot: nb->nb_remainder = (binaryfunc)f; break; case floordiv_slot: nb->nb_floor_divide = (binaryfunc)f; break; case truediv_slot: nb->nb_true_divide = (binaryfunc)f; break; case and_slot: nb->nb_and = (binaryfunc)f; break; case or_slot: nb->nb_or = (binaryfunc)f; break; case xor_slot: nb->nb_xor = (binaryfunc)f; break; case lshift_slot: nb->nb_lshift = (binaryfunc)f; break; case rshift_slot: nb->nb_rshift = (binaryfunc)f; break; case iadd_slot: nb->nb_inplace_add = (binaryfunc)f; break; case iconcat_slot: sq->sq_inplace_concat = (binaryfunc)f; break; case isub_slot: nb->nb_inplace_subtract = (binaryfunc)f; break; case imul_slot: nb->nb_inplace_multiply = (binaryfunc)f; break; case irepeat_slot: sq->sq_inplace_repeat = (ssizeargfunc)f; break; case idiv_slot: nb->nb_inplace_true_divide = (binaryfunc)f; break; case imod_slot: nb->nb_inplace_remainder = (binaryfunc)f; break; case ifloordiv_slot: nb->nb_inplace_floor_divide = (binaryfunc)f; break; case itruediv_slot: nb->nb_inplace_true_divide = (binaryfunc)f; break; case iand_slot: nb->nb_inplace_and = (binaryfunc)f; break; case ior_slot: nb->nb_inplace_or = (binaryfunc)f; break; case ixor_slot: nb->nb_inplace_xor = (binaryfunc)f; break; case ilshift_slot: nb->nb_inplace_lshift = (binaryfunc)f; break; case irshift_slot: nb->nb_inplace_rshift = (binaryfunc)f; break; case invert_slot: nb->nb_invert = (unaryfunc)f; break; case call_slot: to->tp_call = slot_call; break; case getitem_slot: mp->mp_subscript = (binaryfunc)f; sq->sq_item = slot_sq_item; break; case setitem_slot: case delitem_slot: mp->mp_ass_subscript = slot_mp_ass_subscript; sq->sq_ass_item = slot_sq_ass_item; break; case lt_slot: case le_slot: case eq_slot: case ne_slot: case gt_slot: case ge_slot: to->tp_richcompare = slot_richcompare; break; case bool_slot: nb->nb_bool = (inquiry)f; break; case neg_slot: nb->nb_negative = (unaryfunc)f; break; case repr_slot: to->tp_repr = (reprfunc)f; break; case hash_slot: to->tp_hash = (hashfunc)f; break; case pos_slot: nb->nb_positive = (unaryfunc)f; break; case abs_slot: nb->nb_absolute = (unaryfunc)f; break; case index_slot: nb->nb_index = (unaryfunc)f; break; case iter_slot: to->tp_iter = (getiterfunc)f; break; case next_slot: to->tp_iternext = (iternextfunc)f; break; case setattr_slot: to->tp_setattro = (setattrofunc)f; break; case matmul_slot: nb->nb_matrix_multiply = (binaryfunc)f; break; case imatmul_slot: nb->nb_inplace_matrix_multiply = (binaryfunc)f; break; case await_slot: am->am_await = (unaryfunc)f; break; case aiter_slot: am->am_aiter = (unaryfunc)f; break; case anext_slot: am->am_anext = (unaryfunc)f; break; /* Suppress a compiler warning. */ default: ; } } /* * Remove the object from the map and call the C/C++ dtor if we own the * instance. */ static void forgetObject(sipSimpleWrapper *sw) { sipEventHandler *eh; const sipClassTypeDef *ctd = (const sipClassTypeDef *)((sipWrapperType *)Py_TYPE(sw))->wt_td; /* Invoke any event handlers. */ for (eh = event_handlers[sipEventCollectingWrapper]; eh != NULL; eh = eh->next) { if (is_subtype(ctd, eh->ctd)) { sipCollectingWrapperEventHandler handler = (sipCollectingWrapperEventHandler)eh->handler; handler(sw); } } /* * This is needed because we might release the GIL when calling a C++ dtor. * Without it the cyclic garbage collector can be invoked from another * thread resulting in a crash. */ PyObject_GC_UnTrack((PyObject *)sw); /* * Remove the object from the map before calling the class specific dealloc * code. This code calls the C++ dtor and may result in further calls that * pass the instance as an argument. If this is still in the map then it's * reference count would be increased (to one) and bad things happen when * it drops back to zero again. (An example is PyQt events generated * during the dtor call being passed to an event filter implemented in * Python.) By removing it from the map first we ensure that a new Python * object is created. */ sipOMRemoveObject(&cppPyMap, sw); if (sipInterpreter != NULL) { const sipClassTypeDef *ctd; if (getPtrTypeDef(sw, &ctd) != NULL && ctd->ctd_dealloc != NULL) ctd->ctd_dealloc(sw); } clear_access_func(sw); } /* * If the given name is that of a typedef then the corresponding type is * returned. */ static const char *sip_api_resolve_typedef(const char *name) { const sipExportedModuleDef *em; /* * Note that if the same name is defined as more than one type (which is * possible if more than one completely independent modules are being * used) then we might pick the wrong one. */ for (em = moduleList; em != NULL; em = em->em_next) { if (em->em_nrtypedefs > 0) { sipTypedefDef *tdd; tdd = (sipTypedefDef *)bsearch(name, em->em_typedefs, em->em_nrtypedefs, sizeof (sipTypedefDef), compareTypedefName); if (tdd != NULL) return tdd->tdd_type_name; } } return NULL; } /* * The bsearch() helper function for searching a sorted typedef table. */ static int compareTypedefName(const void *key, const void *el) { return strcmp((const char *)key, ((const sipTypedefDef *)el)->tdd_name); } /* * Add the given Python object to the given list. Return 0 if there was no * error. */ static int addPyObjectToList(sipPyObject **head, PyObject *object) { sipPyObject *po; if ((po = sip_api_malloc(sizeof (sipPyObject))) == NULL) return -1; po->object = object; po->next = *head; *head = po; return 0; } /* * Register a symbol with a name. A negative value is returned if the name was * already registered. */ static int sip_api_export_symbol(const char *name, void *sym) { sipSymbol *ss; if (sip_api_import_symbol(name) != NULL) return -1; if ((ss = sip_api_malloc(sizeof (sipSymbol))) == NULL) return -1; ss->name = name; ss->symbol = sym; ss->next = sipSymbolList; sipSymbolList = ss; return 0; } /* * Return the symbol registered with the given name. NULL is returned if the * name was not registered. */ static void *sip_api_import_symbol(const char *name) { sipSymbol *ss; for (ss = sipSymbolList; ss != NULL; ss = ss->next) if (strcmp(ss->name, name) == 0) return ss->symbol; return NULL; } /* * Convert a Python object to a character and raise an exception if there was * an error. */ static char sip_api_bytes_as_char(PyObject *obj) { char ch; if (parseBytes_AsChar(obj, &ch) < 0) { PyErr_Format(PyExc_TypeError, "bytes of length 1 expected not '%s'", Py_TYPE(obj)->tp_name); return '\0'; } return ch; } /* * Convert a Python object to a string and raise an exception if there was * an error. */ static const char *sip_api_bytes_as_string(PyObject *obj) { const char *a; if (parseBytes_AsString(obj, &a) < 0) { PyErr_Format(PyExc_TypeError, "bytes expected not '%s'", Py_TYPE(obj)->tp_name); return NULL; } return a; } /* * Convert a Python ASCII string object to a character and raise an exception * if there was an error. */ static char sip_api_string_as_ascii_char(PyObject *obj) { char ch; if (parseString_AsASCIIChar(obj, &ch) < 0) ch = '\0'; return ch; } /* * Parse an ASCII character and return it. */ static int parseString_AsASCIIChar(PyObject *obj, char *ap) { if (parseString_AsEncodedChar(PyUnicode_AsASCIIString(obj), obj, ap) < 0) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) PyErr_SetString(PyExc_TypeError, "bytes or ASCII string of length 1 expected"); return -1; } return 0; } /* * Convert a Python Latin-1 string object to a character and raise an exception * if there was an error. */ static char sip_api_string_as_latin1_char(PyObject *obj) { char ch; if (parseString_AsLatin1Char(obj, &ch) < 0) ch = '\0'; return ch; } /* * Parse a Latin-1 character and return it via a pointer. */ static int parseString_AsLatin1Char(PyObject *obj, char *ap) { if (parseString_AsEncodedChar(PyUnicode_AsLatin1String(obj), obj, ap) < 0) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) PyErr_SetString(PyExc_TypeError, "bytes or Latin-1 string of length 1 expected"); return -1; } return 0; } /* * Convert a Python UTF-8 string object to a character and raise an exception * if there was an error. */ static char sip_api_string_as_utf8_char(PyObject *obj) { char ch; if (parseString_AsUTF8Char(obj, &ch) < 0) ch = '\0'; return ch; } /* * Parse a UTF-8 character and return it. */ static int parseString_AsUTF8Char(PyObject *obj, char *ap) { if (parseString_AsEncodedChar(PyUnicode_AsUTF8String(obj), obj, ap) < 0) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(obj) || PyUnicode_GET_LENGTH(obj) != 1) PyErr_SetString(PyExc_TypeError, "bytes or UTF-8 string of length 1 expected"); return -1; } return 0; } /* * Parse an encoded character and return it. */ static int parseString_AsEncodedChar(PyObject *bytes, PyObject *obj, char *ap) { Py_ssize_t size; if (bytes == NULL) { PyErr_Clear(); return parseBytes_AsChar(obj, ap); } size = PyBytes_GET_SIZE(bytes); if (size != 1) { Py_DECREF(bytes); return -1; } if (ap != NULL) *ap = *PyBytes_AS_STRING(bytes); Py_DECREF(bytes); return 0; } /* * Convert a Python ASCII string object to a string and raise an exception if * there was an error. The object is updated with the one that owns the * string. Note that None is considered an error. */ static const char *sip_api_string_as_ascii_string(PyObject **obj) { PyObject *s = *obj; const char *a; if (s == Py_None || (*obj = parseString_AsASCIIString(s, &a)) == NULL) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(s)) PyErr_Format(PyExc_TypeError, "bytes or ASCII string expected not '%s'", Py_TYPE(s)->tp_name); return NULL; } return a; } /* * Parse an ASCII string and return it and a new reference to the object that * owns the string. */ static PyObject *parseString_AsASCIIString(PyObject *obj, const char **ap) { return parseString_AsEncodedString(PyUnicode_AsASCIIString(obj), obj, ap); } /* * Convert a Python Latin-1 string object to a string and raise an exception if * there was an error. The object is updated with the one that owns the * string. Note that None is considered an error. */ static const char *sip_api_string_as_latin1_string(PyObject **obj) { PyObject *s = *obj; const char *a; if (s == Py_None || (*obj = parseString_AsLatin1String(s, &a)) == NULL) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(s)) PyErr_Format(PyExc_TypeError, "bytes or Latin-1 string expected not '%s'", Py_TYPE(s)->tp_name); return NULL; } return a; } /* * Parse a Latin-1 string and return it and a new reference to the object that * owns the string. */ static PyObject *parseString_AsLatin1String(PyObject *obj, const char **ap) { return parseString_AsEncodedString(PyUnicode_AsLatin1String(obj), obj, ap); } /* * Convert a Python UTF-8 string object to a string and raise an exception if * there was an error. The object is updated with the one that owns the * string. Note that None is considered an error. */ static const char *sip_api_string_as_utf8_string(PyObject **obj) { PyObject *s = *obj; const char *a; if (s == Py_None || (*obj = parseString_AsUTF8String(s, &a)) == NULL) { /* Use the exception set if it was an encoding error. */ if (!PyUnicode_Check(s)) PyErr_Format(PyExc_TypeError, "bytes or UTF-8 string expected not '%s'", Py_TYPE(s)->tp_name); return NULL; } return a; } /* * Parse a UTF-8 string and return it and a new reference to the object that * owns the string. */ static PyObject *parseString_AsUTF8String(PyObject *obj, const char **ap) { return parseString_AsEncodedString(PyUnicode_AsUTF8String(obj), obj, ap); } /* * Parse an encoded string and return it and a new reference to the object that * owns the string. */ static PyObject *parseString_AsEncodedString(PyObject *bytes, PyObject *obj, const char **ap) { if (bytes != NULL) { *ap = PyBytes_AS_STRING(bytes); return bytes; } /* Don't try anything else if there was an encoding error. */ if (PyUnicode_Check(obj)) return NULL; PyErr_Clear(); if (parseBytes_AsString(obj, ap) < 0) return NULL; Py_INCREF(obj); return obj; } /* * Parse a character array and return it's address and length. */ static int parseBytes_AsCharArray(PyObject *obj, const char **ap, Py_ssize_t *aszp) { const char *a; Py_ssize_t asz; if (obj == Py_None) { a = NULL; asz = 0; } else if (PyBytes_Check(obj)) { a = PyBytes_AS_STRING(obj); asz = PyBytes_GET_SIZE(obj); } else { Py_buffer view; if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) return -1; a = view.buf; asz = view.len; PyBuffer_Release(&view); } if (ap != NULL) *ap = a; if (aszp != NULL) *aszp = asz; return 0; } /* * Parse a character and return it. */ static int parseBytes_AsChar(PyObject *obj, char *ap) { const char *chp; Py_ssize_t sz; if (PyBytes_Check(obj)) { chp = PyBytes_AS_STRING(obj); sz = PyBytes_GET_SIZE(obj); } else { Py_buffer view; if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) return -1; chp = view.buf; sz = view.len; PyBuffer_Release(&view); } if (sz != 1) return -1; if (ap != NULL) *ap = *chp; return 0; } /* * Parse a character string and return it. */ static int parseBytes_AsString(PyObject *obj, const char **ap) { const char *a; Py_ssize_t sz; if (parseBytes_AsCharArray(obj, &a, &sz) < 0) return -1; if (ap != NULL) *ap = a; return 0; } #if defined(HAVE_WCHAR_H) /* * Convert a Python object to a wide character. */ static wchar_t sip_api_unicode_as_wchar(PyObject *obj) { wchar_t ch; if (parseWChar(obj, &ch) < 0) { PyErr_Format(PyExc_ValueError, "string of length 1 expected, not %s", Py_TYPE(obj)->tp_name); return L'\0'; } return ch; } /* * Convert a Python object to a wide character string on the heap. */ static wchar_t *sip_api_unicode_as_wstring(PyObject *obj) { wchar_t *p; if (parseWCharString(obj, &p) < 0) { PyErr_Format(PyExc_ValueError, "string expected, not %s", Py_TYPE(obj)->tp_name); return NULL; } return p; } /* * Parse a wide character array and return it's address and length. */ static int parseWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp) { wchar_t *a; Py_ssize_t asz; if (obj == Py_None) { a = NULL; asz = 0; } else if (PyUnicode_Check(obj)) { if (convertToWCharArray(obj, &a, &asz) < 0) return -1; } else { return -1; } if (ap != NULL) *ap = a; if (aszp != NULL) *aszp = asz; return 0; } /* * Convert a Unicode object to a wide character array and return it's address * and length. */ static int convertToWCharArray(PyObject *obj, wchar_t **ap, Py_ssize_t *aszp) { Py_ssize_t ulen; wchar_t *wc; ulen = PyUnicode_GET_LENGTH(obj); if ((wc = sip_api_malloc(ulen * sizeof (wchar_t))) == NULL) return -1; if ((ulen = PyUnicode_AsWideChar(obj, wc, ulen)) < 0) { sip_api_free(wc); return -1; } *ap = wc; *aszp = ulen; return 0; } /* * Parse a wide character and return it. */ static int parseWChar(PyObject *obj, wchar_t *ap) { wchar_t a; if (PyUnicode_Check(obj)) { if (convertToWChar(obj, &a) < 0) return -1; } else { return -1; } if (ap != NULL) *ap = a; return 0; } /* * Convert a Unicode object to a wide character and return it. */ static int convertToWChar(PyObject *obj, wchar_t *ap) { if (PyUnicode_GET_LENGTH(obj) != 1) return -1; if (PyUnicode_AsWideChar(obj, ap, 1) != 1) return -1; return 0; } /* * Parse a wide character string and return a copy on the heap. */ static int parseWCharString(PyObject *obj, wchar_t **ap) { wchar_t *a; if (obj == Py_None) { a = NULL; } else if (PyUnicode_Check(obj)) { if (convertToWCharString(obj, &a) < 0) return -1; } else { return -1; } if (ap != NULL) *ap = a; return 0; } /* * Convert a Unicode object to a wide character string and return a copy on * the heap. */ static int convertToWCharString(PyObject *obj, wchar_t **ap) { Py_ssize_t ulen; wchar_t *wc; ulen = PyUnicode_GET_LENGTH(obj); if ((wc = sip_api_malloc((ulen + 1) * sizeof (wchar_t))) == NULL) return -1; if ((ulen = PyUnicode_AsWideChar(obj, wc, ulen)) < 0) { sip_api_free(wc); return -1; } wc[ulen] = L'\0'; *ap = wc; return 0; } #else /* * Convert a Python object to a wide character. */ static int sip_api_unicode_as_wchar(PyObject *obj) { raiseNoWChar(); return 0; } /* * Convert a Python object to a wide character. */ static int *sip_api_unicode_as_wstring(PyObject *obj) { raiseNoWChar(); return NULL; } /* * Report the need for absent wide character support. */ static void raiseNoWChar() { PyErr_SetString(PyExc_SystemError, _SIP_MODULE_FQ_NAME " built without wchar_t support"); } #endif /* * Check if an object is of the right type to convert to an encoded string. */ static int check_encoded_string(PyObject *obj) { Py_buffer view; if (obj == Py_None) return 0; if (PyUnicode_Check(obj)) return 0; if (PyBytes_Check(obj)) return 0; if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) { PyErr_Clear(); } else { PyBuffer_Release(&view); return 0; } return -1; } /* * This is called by the atexit module. */ static PyObject *sip_exit(PyObject *self, PyObject *args) { (void)self; (void)args; /* Disable all Python reimplementations of virtuals. */ sipInterpreter = NULL; Py_INCREF(Py_None); return Py_None; } /* * Register an exit notifier with the atexit module. */ static int sip_api_register_exit_notifier(PyMethodDef *md) { static PyObject *register_func = NULL; PyObject *notifier, *res; if (register_func == NULL && (register_func = import_module_attr("atexit", "register")) == NULL) return -1; if ((notifier = PyCFunction_New(md, NULL)) == NULL) return -1; res = PyObject_CallFunctionObjArgs(register_func, notifier, NULL); Py_DECREF(notifier); if (res == NULL) return -1; Py_DECREF(res); return 0; } /* * Return the function that converts a C++ instance to a Python object. */ static sipConvertFromFunc get_from_convertor(const sipTypeDef *td) { if (sipTypeIsMapped(td)) return ((const sipMappedTypeDef *)td)->mtd_cfrom; assert(sipTypeIsClass(td)); if (autoconversion_disabled(td) != NULL) return NULL; return ((const sipClassTypeDef *)td)->ctd_cfrom; } /* * Enable or disable the auto-conversion. Returns the previous enabled state * or -1 on error. */ static int sip_api_enable_autoconversion(const sipTypeDef *td, int enable) { sipPyObject **pop; assert(sipTypeIsClass(td)); pop = autoconversion_disabled(td); /* See if there is anything to do. */ if (pop == NULL && enable) return TRUE; if (pop != NULL && !enable) return FALSE; if (pop != NULL) { /* Remove it from the list. */ sipPyObject *po = *pop; *pop = po->next; sip_api_free(po); } else { /* Add it to the list. */ if (addPyObjectToList(&sipDisabledAutoconversions, (PyObject *)sipTypeAsPyTypeObject(td)) < 0) return -1; } return !enable; } /* * Return a pointer to the entry in the list of disabled auto-conversions for a * type. */ static sipPyObject **autoconversion_disabled(const sipTypeDef *td) { PyObject *type = (PyObject *)sipTypeAsPyTypeObject(td); sipPyObject **pop; for (pop = &sipDisabledAutoconversions; *pop != NULL; pop = &(*pop)->next) if ((*pop)->object == type) return pop; return NULL; } /* * Enable or disable auto-conversion of a class that supports it. */ static PyObject *enableAutoconversion(PyObject *self, PyObject *args) { sipWrapperType *wt; int enable; (void)self; if (PyArg_ParseTuple(args, "O!i:enableautoconversion", &sipWrapperType_Type, &wt, &enable)) { sipTypeDef *td = wt->wt_td; int was_enabled; PyObject *res; if (!sipTypeIsClass(td) || ((sipClassTypeDef *)td)->ctd_cfrom == NULL) { PyErr_Format(PyExc_TypeError, "%s is not a wrapped class that supports optional auto-conversion", ((PyTypeObject *)wt)->tp_name); return NULL; } if ((was_enabled = sip_api_enable_autoconversion(td, enable)) < 0) return NULL; res = (was_enabled ? Py_True : Py_False); Py_INCREF(res); return res; } return NULL; } /* * Python copies the nb_inplace_add slot to the sq_inplace_concat slot and vice * versa if either are missing. This is a bug because they don't have the same * API. We therefore reverse this. */ static void fix_slots(PyTypeObject *py_type, sipPySlotDef *psd) { while (psd->psd_func != NULL) { if (psd->psd_type == iadd_slot && py_type->tp_as_sequence != NULL) py_type->tp_as_sequence->sq_inplace_concat = NULL; if (psd->psd_type == iconcat_slot && py_type->tp_as_number != NULL) py_type->tp_as_number->nb_inplace_add = NULL; ++psd; } } /* * Return the main instance for an object if it is a mixin. */ static sipSimpleWrapper *deref_mixin(sipSimpleWrapper *w) { return w->mixin_main != NULL ? (sipSimpleWrapper *)w->mixin_main : w; } /* * Convert a new C/C++ pointer to a Python instance. */ static PyObject *wrap_simple_instance(void *cpp, const sipTypeDef *td, sipWrapper *owner, int flags) { return sipWrapInstance(cpp, sipTypeAsPyTypeObject(td), empty_tuple, owner, flags); } /* * Resolve a proxy, if applicable. */ static void *resolve_proxy(const sipTypeDef *td, void *proxy) { sipProxyResolver *pr; /* TODO: Deprecate this mechanism in favour of an event handler. */ for (pr = proxyResolvers; pr != NULL; pr = pr->next) if (pr->td == td) proxy = pr->resolver(proxy); return proxy; } /* * Clear a simple wrapper. */ static void clear_wrapper(sipSimpleWrapper *sw) { if (PyObject_TypeCheck((PyObject *)sw, (PyTypeObject *)&sipWrapper_Type)) removeFromParent((sipWrapper *)sw); /* * Transfer ownership to C++ so we don't try to release it when the * Python object is garbage collected. */ sipResetPyOwned(sw); sipOMRemoveObject(&cppPyMap, sw); clear_access_func(sw); } /* * Set the user-specific type data. */ static void sip_api_set_type_user_data(sipWrapperType *wt, void *data) { wt->wt_user_data = data; } /* * Get the user-specific type data. */ static void *sip_api_get_type_user_data(const sipWrapperType *wt) { return wt->wt_user_data; } /* * Get the dict of a Python type (on behalf of the limited API). */ static PyObject *sip_api_py_type_dict(const PyTypeObject *py_type) { return py_type->tp_dict; } /* * Get the name of a Python type (on behalf of the limited API). */ static const char *sip_api_py_type_name(const PyTypeObject *py_type) { return py_type->tp_name; } /* * Check an object is a method and return TRUE and its component parts if it * is. */ static int sip_api_get_method(PyObject *obj, sipMethodDef *method) { if (!PyMethod_Check(obj)) return FALSE; if (method != NULL) { method->pm_self = PyMethod_GET_SELF(obj); method->pm_function = PyMethod_GET_FUNCTION(obj); } return TRUE; } /* * Create a method from its component parts. */ static PyObject *sip_api_from_method(const sipMethodDef *method) { return PyMethod_New(method->pm_function, method->pm_self); } /* * Check an object is a C function and return TRUE and its component parts if * it is. */ static int sip_api_get_c_function(PyObject *obj, sipCFunctionDef *c_function) { if (!PyCFunction_Check(obj)) return FALSE; if (c_function != NULL) { c_function->cf_function = ((PyCFunctionObject *)obj)->m_ml; c_function->cf_self = PyCFunction_GET_SELF(obj); } return TRUE; } /* * Check an object is a date and return TRUE and its component parts if it is. */ static int sip_api_get_date(PyObject *obj, sipDateDef *date) { if (!PyDateTimeAPI) PyDateTime_IMPORT; if (!PyDate_Check(obj)) return FALSE; if (date != NULL) { date->pd_year = PyDateTime_GET_YEAR(obj); date->pd_month = PyDateTime_GET_MONTH(obj); date->pd_day = PyDateTime_GET_DAY(obj); } return TRUE; } /* * Create a date from its component parts. */ static PyObject *sip_api_from_date(const sipDateDef *date) { if (!PyDateTimeAPI) PyDateTime_IMPORT; return PyDate_FromDate(date->pd_year, date->pd_month, date->pd_day); } /* * Check an object is a datetime and return TRUE and its component parts if it * is. */ static int sip_api_get_datetime(PyObject *obj, sipDateDef *date, sipTimeDef *time) { if (!PyDateTimeAPI) PyDateTime_IMPORT; if (!PyDateTime_Check(obj)) return FALSE; if (date != NULL) { date->pd_year = PyDateTime_GET_YEAR(obj); date->pd_month = PyDateTime_GET_MONTH(obj); date->pd_day = PyDateTime_GET_DAY(obj); } if (time != NULL) { time->pt_hour = PyDateTime_DATE_GET_HOUR(obj); time->pt_minute = PyDateTime_DATE_GET_MINUTE(obj); time->pt_second = PyDateTime_DATE_GET_SECOND(obj); time->pt_microsecond = PyDateTime_DATE_GET_MICROSECOND(obj); } return TRUE; } /* * Create a datetime from its component parts. */ static PyObject *sip_api_from_datetime(const sipDateDef *date, const sipTimeDef *time) { if (!PyDateTimeAPI) PyDateTime_IMPORT; return PyDateTime_FromDateAndTime(date->pd_year, date->pd_month, date->pd_day, time->pt_hour, time->pt_minute, time->pt_second, time->pt_microsecond); } /* * Check an object is a time and return TRUE and its component parts if it is. */ static int sip_api_get_time(PyObject *obj, sipTimeDef *time) { if (!PyDateTimeAPI) PyDateTime_IMPORT; if (!PyTime_Check(obj)) return FALSE; if (time != NULL) { time->pt_hour = PyDateTime_TIME_GET_HOUR(obj); time->pt_minute = PyDateTime_TIME_GET_MINUTE(obj); time->pt_second = PyDateTime_TIME_GET_SECOND(obj); time->pt_microsecond = PyDateTime_TIME_GET_MICROSECOND(obj); } return TRUE; } /* * Create a time from its component parts. */ static PyObject *sip_api_from_time(const sipTimeDef *time) { if (!PyDateTimeAPI) PyDateTime_IMPORT; return PyTime_FromTime(time->pt_hour, time->pt_minute, time->pt_second, time->pt_microsecond); } /* * See if a type is user defined. */ static int sip_api_is_user_type(const sipWrapperType *wt) { return wt->wt_user_type; } /* * Check if a type was generated using the given plugin. Note that, although * this is part of the public API it is undocumented on purpose. */ static int sip_api_check_plugin_for_type(const sipTypeDef *td, const char *name) { /* * The current thinking on plugins is that SIP v7 will look for a plugin * with a name derived from the name as the current module in the same * directory as the .sip defining the module (ie. no %Plugin directive). A * module hierachy may have multiple plugins but they must co-operate. If * a plugin generates user data then it should include a void* (and a * run-time API) so that other plugins can extend it further. This * approach means that a plugin's user data structure can be opaque. */ sipExportedModuleDef *em = td->td_module; sipImportedModuleDef *im; if (strcmp(sipNameOfModule(em), name) == 0) return TRUE; if ((im = em->em_imports) == NULL) return FALSE; while (im->im_name != NULL) { if (strcmp(im->im_name, name) == 0) return TRUE; ++im; } return FALSE; } /* * Create a new Unicode object and return the character size and buffer. */ static PyObject *sip_api_unicode_new(Py_ssize_t len, unsigned maxchar, int *kind, void **data) { PyObject *obj; if ((obj = PyUnicode_New(len, maxchar)) != NULL) { *kind = PyUnicode_KIND(obj); *data = PyUnicode_DATA(obj); } return obj; } /* * Update a new Unicode object with a new character. */ static void sip_api_unicode_write(int kind, void *data, int index, unsigned value) { PyUnicode_WRITE(kind, data, index, value); } /* * Get the address of the contents of a Unicode object, the character size and * the length. */ static void *sip_api_unicode_data(PyObject *obj, int *char_size, Py_ssize_t *len) { void *data; /* Assume there will be an error. */ *char_size = -1; if (PyUnicode_READY(obj) < 0) return NULL; *len = PyUnicode_GET_LENGTH(obj); switch (PyUnicode_KIND(obj)) { case PyUnicode_1BYTE_KIND: *char_size = 1; data = PyUnicode_1BYTE_DATA(obj); break; case PyUnicode_2BYTE_KIND: *char_size = 2; data = PyUnicode_2BYTE_DATA(obj); break; case PyUnicode_4BYTE_KIND: *char_size = 4; data = PyUnicode_4BYTE_DATA(obj); break; default: data = NULL; } return data; } /* * Get the buffer information supplied by an object that supports the buffer * protocol. */ static int sip_api_get_buffer_info(PyObject *obj, sipBufferInfoDef *bi) { int rc; Py_buffer *buffer; if (!PyObject_CheckBuffer(obj)) return 0; if (bi == NULL) return 1; if ((bi->bi_internal = sip_api_malloc(sizeof (Py_buffer))) == NULL) return -1; buffer = (Py_buffer *)bi->bi_internal; if (PyObject_GetBuffer(obj, buffer, PyBUF_FORMAT) < 0) return -1; if (buffer->ndim == 1) { bi->bi_buf = buffer->buf; bi->bi_obj = buffer->obj; bi->bi_len = buffer->len; bi->bi_readonly = buffer->readonly; bi->bi_format = buffer->format; rc = 1; } else { PyErr_SetString(PyExc_TypeError, "a 1-dimensional buffer is required"); PyBuffer_Release(buffer); rc = -1; } return rc; } /* * Release the buffer information obtained from a previous call to * sipGetBufferInfo(). */ static void sip_api_release_buffer_info(sipBufferInfoDef *bi) { if (bi->bi_internal != NULL) { PyBuffer_Release((Py_buffer *)bi->bi_internal); sip_api_free(bi->bi_internal); bi->bi_internal = NULL; } } /* * Import all the required types from an imported module. */ static int importTypes(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em) { const char *name; int i, e; /* * Look for each required type in turn. Both tables are sorted so a single * pass will find them all. */ for (i = e = 0; (name = im->im_imported_types[i].it_name) != NULL; ++i) { sipTypeDef *td = NULL; do { sipTypeDef *e_td; if (e >= em->em_nrtypes) { PyErr_Format(PyExc_RuntimeError, "%s cannot import type '%s' from %s", sipNameOfModule(client), name, sipNameOfModule(em)); return -1; } e_td = em->em_types[e++]; /* Ignore unresolved external types. */ if (e_td != NULL && strcmp(name, sipTypeName(e_td)) == 0) td = e_td; } while (td == NULL); im->im_imported_types[i].it_td = td; } return 0; } /* * Import all the required virtual error handlers from an imported module. */ static int importErrorHandlers(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em) { const char *name; int i; for (i = 0; (name = im->im_imported_veh[i].iveh_name) != NULL; ++i) { sipVirtErrorHandlerDef *veh = em->em_virterrorhandlers; sipVirtErrorHandlerFunc handler = NULL; if (veh != NULL) { while (veh->veh_name != NULL) { if (strcmp(veh->veh_name, name) == 0) { handler = veh->veh_handler; break; } ++veh; } } if (handler == NULL) { PyErr_Format(PyExc_RuntimeError, "%s cannot import virtual error handler '%s' from %s", sipNameOfModule(client), name, sipNameOfModule(em)); return -1; } im->im_imported_veh[i].iveh_handler = handler; } return 0; } /* * Import all the required exceptions from an imported module. */ static int importExceptions(sipExportedModuleDef *client, sipImportedModuleDef *im, sipExportedModuleDef *em) { const char *name; int i; for (i = 0; (name = im->im_imported_exceptions[i].iexc_name) != NULL; ++i) { PyObject **exc = em->em_exceptions; PyObject *exception = NULL; if (exc != NULL) { while (*exc != NULL) { if (strcmp(((PyTypeObject *)(*exc))->tp_name, name) == 0) { exception = *exc; break; } ++exc; } } if (exception == NULL) { PyErr_Format(PyExc_RuntimeError, "%s cannot import exception '%s' from %s", sipNameOfModule(client), name, sipNameOfModule(em)); return -1; } im->im_imported_exceptions[i].iexc_object = exception; } return 0; } /* * Enable or disable the garbage collector. Return the previous state or -1 if * there was an error. */ static int sip_api_enable_gc(int enable) { static PyObject *enable_func = NULL, *disable_func, *isenabled_func; PyObject *result; int was_enabled; /* * This may be -ve in the highly unusual event that a previous call failed. */ if (enable < 0) return -1; /* Get the functions if we haven't already got them. */ if (enable_func == NULL) { PyObject *gc_module; if ((gc_module = PyImport_ImportModule("gc")) == NULL) return -1; if ((enable_func = PyObject_GetAttrString(gc_module, "enable")) == NULL) { Py_DECREF(gc_module); return -1; } if ((disable_func = PyObject_GetAttrString(gc_module, "disable")) == NULL) { Py_DECREF(enable_func); Py_DECREF(gc_module); return -1; } if ((isenabled_func = PyObject_GetAttrString(gc_module, "isenabled")) == NULL) { Py_DECREF(disable_func); Py_DECREF(enable_func); Py_DECREF(gc_module); return -1; } Py_DECREF(gc_module); } /* Get the current state. */ if ((result = PyObject_Call(isenabled_func, empty_tuple, NULL)) == NULL) return -1; was_enabled = PyObject_IsTrue(result); Py_DECREF(result); if (was_enabled < 0) return -1; /* See if the state needs changing. */ if (!was_enabled != !enable) { /* Enable or disable as required. */ result = PyObject_Call((enable ? enable_func : disable_func), empty_tuple, NULL); Py_XDECREF(result); if (result != Py_None) return -1; } return was_enabled; } /* * A thin wrapper around PyObject_Print() usually used when debugging with the * limited API. */ static void sip_api_print_object(PyObject *o) { PyObject_Print(o, stdout, 0); } /* * Register a handler for a particular event. */ static int sip_api_register_event_handler(sipEventType type, const sipTypeDef *td, void *handler) { sipEventHandler *eh; assert(sipTypeIsClass(td)); if ((eh = sip_api_malloc(sizeof (sipEventHandler))) == NULL) return -1; eh->ctd = (const sipClassTypeDef *)td; eh->handler = handler; eh->next = event_handlers[(int)type]; event_handlers[(int)type] = eh; return 0; } /* * Returns TRUE if a generated class type is a sub-class of a base generated * class type. */ static int is_subtype(const sipClassTypeDef *ctd, const sipClassTypeDef *base_ctd) { const sipEncodedTypeDef *sup; /* Handle the trivial cases. */ if (ctd == base_ctd) return TRUE; if ((sup = ctd->ctd_supers) == NULL) return FALSE; /* Search the super-types. */ do { const sipClassTypeDef *sup_ctd = sipGetGeneratedClassType(sup, ctd); if (is_subtype(sup_ctd, base_ctd)) return TRUE; } while (!sup++->sc_flag); return FALSE; } /* * Return an attribute of an imported module. */ static PyObject *import_module_attr(const char *module, const char *attr) { PyObject *mod_obj, *attr_obj; if ((mod_obj = PyImport_ImportModule(module)) == NULL) return NULL; attr_obj = PyObject_GetAttrString(mod_obj, attr); Py_DECREF(mod_obj); return attr_obj; } /* * Get the container for a generated type. */ static const sipContainerDef *get_container(const sipTypeDef *td) { if (sipTypeIsMapped(td)) return &((const sipMappedTypeDef *)td)->mtd_container; return &((const sipClassTypeDef *)td)->ctd_container; } /* * Get the __qualname__ of an object based on its enclosing scope. */ static PyObject *get_qualname(const sipTypeDef *td, PyObject *name) { PyTypeObject *scope_type; /* Get the type that is the scope. */ scope_type = sipTypeAsPyTypeObject(td); return PyUnicode_FromFormat("%U.%U", ((PyHeapTypeObject *)scope_type)->ht_qualname, name); } /* * Implement PySlice_GetIndicesEx() (or its subsequent replacement). */ int sip_api_convert_from_slice_object(PyObject *slice, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength) { #if PY_VERSION_HEX >= 0x03070000 if (PySlice_Unpack(slice, start, stop, step) < 0) return -1; *slicelength = PySlice_AdjustIndices(length, start, stop, *step); return 0; #else return PySlice_GetIndicesEx(slice, length, start, stop, step, slicelength); #endif } /* * Call a visitor function for every wrapped object. */ static void sip_api_visit_wrappers(sipWrapperVisitorFunc visitor, void *closure) { const sipHashEntry *he; unsigned long i; for (he = cppPyMap.hash_array, i = 0; i < cppPyMap.size; ++i, ++he) { if (he->key != NULL) { sipSimpleWrapper *sw; for (sw = he->first; sw != NULL; sw = sw->next) visitor(sw, closure); } } } /* * Raise an exception when there is no mapped type converter to convert from * C/C++ to Python. */ static void raise_no_convert_from(const sipTypeDef *td) { PyErr_Format(PyExc_TypeError, "%s cannot be converted to a Python object", sipTypeName(td)); } /* * Raise an exception when there is no mapped type converter to convert to * C/C++ from Python. */ static void raise_no_convert_to(PyObject *py, const sipTypeDef *td) { PyErr_Format(PyExc_TypeError, "%s cannot be converted to %s", Py_TYPE(py)->tp_name, sipTypeName(td)); } /* * Check that a user state pointer has been provided if the type requires it. * This is most likely a problem with handwritten code. */ static int user_state_is_valid(const sipTypeDef *td, void **user_statep) { if (sipTypeNeedsUserState(td) && user_statep == NULL) { PyErr_Format(PyExc_RuntimeError, "%s requires user state but none is provided", sipTypeName(td)); return FALSE; } return TRUE; } /* * Return the next exception handler. The order is undefined. */ sipExceptionHandler sip_api_next_exception_handler(void **statep) { sipExportedModuleDef *em = *(sipExportedModuleDef **)statep; if (em != NULL) em = em->em_next; else em = moduleList; while (em->em_exception_handler == NULL) if ((em = em->em_next) == NULL) return NULL; *statep = em; return em->em_exception_handler; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/threads.c0000644000076500000240000001126200000000000014054 0ustar00philstaff/* * Thread support for the SIP library. This module provides the hooks for * C++ classes that provide a thread interface to interact properly with the * Python threading infrastructure. * * Copyright (c) 2020 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include "sipint.h" /* * The data associated with pending request to wrap an object. */ typedef struct _pendingDef { void *cpp; /* The C/C++ object ot be wrapped. */ sipWrapper *owner; /* The owner of the object. */ int flags; /* The flags. */ } pendingDef; #ifdef WITH_THREAD #include /* * The per thread data we need to maintain. */ typedef struct _threadDef { long thr_ident; /* The thread identifier. */ pendingDef pending; /* An object waiting to be wrapped. */ struct _threadDef *next; /* Next in the list. */ } threadDef; static threadDef *threads = NULL; /* Linked list of threads. */ static threadDef *currentThreadDef(int auto_alloc); #endif static pendingDef *get_pending(int auto_alloc); /* * Get the address etc. of any C/C++ object waiting to be wrapped. */ int sipGetPending(void **pp, sipWrapper **op, int *fp) { pendingDef *pd; if ((pd = get_pending(TRUE)) == NULL) return -1; *pp = pd->cpp; *op = pd->owner; *fp = pd->flags; /* Clear in case we execute Python code before finishing this wrapping. */ pd->cpp = NULL; return 0; } /* * Return TRUE if anything is pending. */ int sipIsPending(void) { pendingDef *pd; if ((pd = get_pending(FALSE)) == NULL) return FALSE; return (pd->cpp != NULL); } /* * Convert a new C/C++ pointer to a Python instance. */ PyObject *sipWrapInstance(void *cpp, PyTypeObject *py_type, PyObject *args, sipWrapper *owner, int flags) { pendingDef old_pending, *pd; PyObject *self; if (cpp == NULL) { Py_INCREF(Py_None); return Py_None; } /* * Object creation can trigger the Python garbage collector which in turn * can execute arbitrary Python code which can then call this function * recursively. Therefore we save any existing pending object before * setting the new one. */ if ((pd = get_pending(TRUE)) == NULL) return NULL; old_pending = *pd; pd->cpp = cpp; pd->owner = owner; pd->flags = flags; self = PyObject_Call((PyObject *)py_type, args, NULL); *pd = old_pending; return self; } /* * Handle the termination of a thread. */ void sip_api_end_thread(void) { #ifdef WITH_THREAD threadDef *thread; PyGILState_STATE gil = PyGILState_Ensure(); if ((thread = currentThreadDef(FALSE)) != NULL) thread->thr_ident = 0; PyGILState_Release(gil); #endif } /* * Return the pending data for the current thread, allocating it if necessary, * or NULL if there was an error. */ static pendingDef *get_pending(int auto_alloc) { #ifdef WITH_THREAD threadDef *thread; if ((thread = currentThreadDef(auto_alloc)) == NULL) return NULL; return &thread->pending; #else static pendingDef pending; return &pending; #endif } #ifdef WITH_THREAD /* * Return the thread data for the current thread, allocating it if necessary, * or NULL if there was an error. */ static threadDef *currentThreadDef(int auto_alloc) { threadDef *thread, *empty = NULL; long ident = PyThread_get_thread_ident(); /* See if we already know about the thread. */ for (thread = threads; thread != NULL; thread = thread->next) { if (thread->thr_ident == ident) return thread; if (thread->thr_ident == 0) empty = thread; } if (!auto_alloc) { /* This is not an error. */ return NULL; } if (empty != NULL) { /* Use an empty entry in the list. */ thread = empty; } else if ((thread = sip_api_malloc(sizeof (threadDef))) == NULL) { return NULL; } else { thread->next = threads; threads = thread; } thread->thr_ident = ident; thread->pending.cpp = NULL; return thread; } #endif ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1643722416.0 PyQt6_sip-13.2.1/voidptr.c0000644000076500000240000004525500000000000014122 0ustar00philstaff/* * SIP library code. * * Copyright (c) 2021 Riverbank Computing Limited * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * This copy of SIP may also used under the terms of the GNU General Public * License v2 or v3 as published by the Free Software Foundation which can be * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include "sipint.h" #include "array.h" /* The object data structure. */ typedef struct { PyObject_HEAD void *voidptr; Py_ssize_t size; int rw; } sipVoidPtrObject; /* The structure used to hold the results of a voidptr conversion. */ struct vp_values { void *voidptr; Py_ssize_t size; int rw; }; static int check_size(PyObject *self); static int check_rw(PyObject *self); static int check_index(PyObject *self, Py_ssize_t idx); static void bad_key(PyObject *key); static int check_slice_size(Py_ssize_t size, Py_ssize_t value_size); static PyObject *make_voidptr(void *voidptr, Py_ssize_t size, int rw); static int vp_convertor(PyObject *arg, struct vp_values *vp); static Py_ssize_t get_size_from_arg(sipVoidPtrObject *v, Py_ssize_t size); /* * Implement ascapsule() for the type. */ static PyObject *sipVoidPtr_ascapsule(sipVoidPtrObject *v, PyObject *arg) { (void)arg; return PyCapsule_New(v->voidptr, NULL, NULL); } /* * Implement asarray() for the type. */ static PyObject *sipVoidPtr_asarray(sipVoidPtrObject *v, PyObject *args, PyObject *kw) { static char *kwlist[] = {"size", NULL}; Py_ssize_t size = -1; if (!PyArg_ParseTupleAndKeywords(args, kw, "|n:asarray", kwlist, &size)) return NULL; if ((size = get_size_from_arg(v, size)) < 0) return NULL; return sip_api_convert_to_array(v->voidptr, "B", size, (v->rw ? 0 : SIP_READ_ONLY)); } /* * Implement asstring() for the type. */ static PyObject *sipVoidPtr_asstring(sipVoidPtrObject *v, PyObject *args, PyObject *kw) { static char *kwlist[] = {"size", NULL}; Py_ssize_t size = -1; if (!PyArg_ParseTupleAndKeywords(args, kw, "|n:asstring", kwlist, &size)) return NULL; if ((size = get_size_from_arg(v, size)) < 0) return NULL; return PyBytes_FromStringAndSize(v->voidptr, size); } /* * Implement getsize() for the type. */ static PyObject *sipVoidPtr_getsize(sipVoidPtrObject *v, PyObject *arg) { (void)arg; return PyLong_FromSsize_t(v->size); } /* * Implement setsize() for the type. */ static PyObject *sipVoidPtr_setsize(sipVoidPtrObject *v, PyObject *arg) { Py_ssize_t size = PyLong_AsSsize_t(arg); if (PyErr_Occurred()) return NULL; v->size = size; Py_INCREF(Py_None); return Py_None; } /* * Implement getwriteable() for the type. */ static PyObject *sipVoidPtr_getwriteable(sipVoidPtrObject *v, PyObject *arg) { (void)arg; return PyBool_FromLong(v->rw); } /* * Implement setwriteable() for the type. */ static PyObject *sipVoidPtr_setwriteable(sipVoidPtrObject *v, PyObject *arg) { int rw; if ((rw = PyObject_IsTrue(arg)) < 0) return NULL; v->rw = rw; Py_INCREF(Py_None); return Py_None; } /* The methods data structure. */ static PyMethodDef sipVoidPtr_Methods[] = { {"asarray", (PyCFunction)sipVoidPtr_asarray, METH_VARARGS|METH_KEYWORDS, NULL}, {"ascapsule", (PyCFunction)sipVoidPtr_ascapsule, METH_NOARGS, NULL}, {"asstring", (PyCFunction)sipVoidPtr_asstring, METH_VARARGS|METH_KEYWORDS, NULL}, {"getsize", (PyCFunction)sipVoidPtr_getsize, METH_NOARGS, NULL}, {"setsize", (PyCFunction)sipVoidPtr_setsize, METH_O, NULL}, {"getwriteable", (PyCFunction)sipVoidPtr_getwriteable, METH_NOARGS, NULL}, {"setwriteable", (PyCFunction)sipVoidPtr_setwriteable, METH_O, NULL}, {NULL, NULL, 0, NULL} }; /* * Implement bool() for the type. */ static int sipVoidPtr_bool(PyObject *self) { return (((sipVoidPtrObject *)self)->voidptr != NULL); } /* * Implement int() for the type. */ static PyObject *sipVoidPtr_int(PyObject *self) { return PyLong_FromVoidPtr(((sipVoidPtrObject *)self)->voidptr); } /* The number methods data structure. */ static PyNumberMethods sipVoidPtr_NumberMethods = { 0, /* nb_add */ 0, /* nb_subtract */ 0, /* nb_multiply */ 0, /* nb_remainder */ 0, /* nb_divmod */ 0, /* nb_power */ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ sipVoidPtr_bool, /* nb_bool */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ sipVoidPtr_int, /* nb_int */ 0, /* nb_reserved */ 0, /* nb_float */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ 0, /* nb_floor_divide */ 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ 0, /* nb_matrix_multiply */ 0, /* nb_inplace_matrix_multiply */ }; /* * Implement len() for the type. */ static Py_ssize_t sipVoidPtr_length(PyObject *self) { if (check_size(self) < 0) return -1; return ((sipVoidPtrObject *)self)->size; } /* * Implement sequence item sub-script for the type. */ static PyObject *sipVoidPtr_item(PyObject *self, Py_ssize_t idx) { if (check_size(self) < 0 || check_index(self, idx) < 0) return NULL; return PyBytes_FromStringAndSize( (char *)((sipVoidPtrObject *)self)->voidptr + idx, 1); } /* The sequence methods data structure. */ static PySequenceMethods sipVoidPtr_SequenceMethods = { sipVoidPtr_length, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ sipVoidPtr_item, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ 0, /* sq_inplace_repeat */ }; /* * Implement mapping sub-script for the type. */ static PyObject *sipVoidPtr_subscript(PyObject *self, PyObject *key) { sipVoidPtrObject *v; if (check_size(self) < 0) return NULL; v = (sipVoidPtrObject *)self; if (PyIndex_Check(key)) { Py_ssize_t idx = PyNumber_AsSsize_t(key, PyExc_IndexError); if (idx == -1 && PyErr_Occurred()) return NULL; if (idx < 0) idx += v->size; return sipVoidPtr_item(self, idx); } if (PySlice_Check(key)) { Py_ssize_t start, stop, step, slicelength; if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &slicelength) < 0) return NULL; if (step != 1) { PyErr_SetNone(PyExc_NotImplementedError); return NULL; } return make_voidptr((char *)v->voidptr + start, slicelength, v->rw); } bad_key(key); return NULL; } /* * Implement mapping assignment sub-script for the type. */ static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { sipVoidPtrObject *v; Py_ssize_t start, size; Py_buffer value_view; if (check_rw(self) < 0 || check_size(self) < 0) return -1; v = (sipVoidPtrObject *)self; if (PyIndex_Check(key)) { start = PyNumber_AsSsize_t(key, PyExc_IndexError); if (start == -1 && PyErr_Occurred()) return -1; if (start < 0) start += v->size; if (check_index(self, start) < 0) return -1; size = 1; } else if (PySlice_Check(key)) { Py_ssize_t stop, step; if (sip_api_convert_from_slice_object(key, v->size, &start, &stop, &step, &size) < 0) return -1; if (step != 1) { PyErr_SetNone(PyExc_NotImplementedError); return -1; } } else { bad_key(key); return -1; } if (PyObject_GetBuffer(value, &value_view, PyBUF_CONTIG_RO) < 0) return -1; /* We could allow any item size... */ if (value_view.itemsize != 1) { PyErr_Format(PyExc_TypeError, "'%s' must have an item size of 1", Py_TYPE(value_view.obj)->tp_name); PyBuffer_Release(&value_view); return -1; } if (check_slice_size(size, value_view.len) < 0) { PyBuffer_Release(&value_view); return -1; } memmove((char *)v->voidptr + start, value_view.buf, size); PyBuffer_Release(&value_view); return 0; } /* The mapping methods data structure. */ static PyMappingMethods sipVoidPtr_MappingMethods = { sipVoidPtr_length, /* mp_length */ sipVoidPtr_subscript, /* mp_subscript */ sipVoidPtr_ass_subscript, /* mp_ass_subscript */ }; /* * The buffer implementation for Python v2.6.3 and later. */ static int sipVoidPtr_getbuffer(PyObject *self, Py_buffer *buf, int flags) { sipVoidPtrObject *v; if (check_size(self) < 0) return -1; v = (sipVoidPtrObject *)self; return PyBuffer_FillInfo(buf, self, v->voidptr, v->size, !v->rw, flags); } /* The buffer methods data structure. */ static PyBufferProcs sipVoidPtr_BufferProcs = { sipVoidPtr_getbuffer, /* bf_getbuffer */ 0 /* bf_releasebuffer */ }; /* * Implement __new__ for the type. */ static PyObject *sipVoidPtr_new(PyTypeObject *subtype, PyObject *args, PyObject *kw) { static char *kwlist[] = {"address", "size", "writeable", NULL}; struct vp_values vp_conversion; Py_ssize_t size = -1; int rw = -1; PyObject *obj; if (!PyArg_ParseTupleAndKeywords(args, kw, "O&|ni:voidptr", kwlist, vp_convertor, &vp_conversion, &size, &rw)) return NULL; /* Use the explicit size if one was given. */ if (size >= 0) vp_conversion.size = size; /* Use the explicit writeable flag if one was given. */ if (rw >= 0) vp_conversion.rw = rw; /* Create the instance. */ if ((obj = subtype->tp_alloc(subtype, 0)) == NULL) return NULL; /* Save the values. */ ((sipVoidPtrObject *)obj)->voidptr = vp_conversion.voidptr; ((sipVoidPtrObject *)obj)->size = vp_conversion.size; ((sipVoidPtrObject *)obj)->rw = vp_conversion.rw; return obj; } /* The type data structure. */ PyTypeObject sipVoidPtr_Type = { PyVarObject_HEAD_INIT(NULL, 0) _SIP_MODULE_FQ_NAME ".voidptr", /* tp_name */ sizeof (sipVoidPtrObject), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved (Python v3), tp_compare (Python v2) */ 0, /* tp_repr */ &sipVoidPtr_NumberMethods, /* tp_as_number */ &sipVoidPtr_SequenceMethods, /* tp_as_sequence */ &sipVoidPtr_MappingMethods, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ &sipVoidPtr_BufferProcs, /* tp_as_buffer */ #if defined(Py_TPFLAGS_HAVE_NEWBUFFER) Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ #endif 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ sipVoidPtr_Methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ sipVoidPtr_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ 0, /* tp_version_tag */ 0, /* tp_finalize */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif }; /* * A convenience function to convert a C/C++ void pointer from a Python object. */ void *sip_api_convert_to_void_ptr(PyObject *obj) { struct vp_values vp; if (obj == NULL) { PyErr_SetString(PyExc_TypeError, _SIP_MODULE_FQ_NAME ".voidptr is NULL"); return NULL; } if (vp_convertor(obj, &vp)) return vp.voidptr; return PyLong_AsVoidPtr(obj); } /* * Convert a C/C++ void pointer to a sip.voidptr object. */ PyObject *sip_api_convert_from_void_ptr(void *val) { return make_voidptr(val, -1, TRUE); } /* * Convert a C/C++ void pointer to a sip.voidptr object. */ PyObject *sip_api_convert_from_const_void_ptr(const void *val) { return make_voidptr((void *)val, -1, FALSE); } /* * Convert a sized C/C++ void pointer to a sip.voidptr object. */ PyObject *sip_api_convert_from_void_ptr_and_size(void *val, Py_ssize_t size) { return make_voidptr(val, size, TRUE); } /* * Convert a sized C/C++ const void pointer to a sip.voidptr object. */ PyObject *sip_api_convert_from_const_void_ptr_and_size(const void *val, Py_ssize_t size) { return make_voidptr((void *)val, size, FALSE); } /* * Check that a void pointer has an explicit size and raise an exception if it * hasn't. */ static int check_size(PyObject *self) { if (((sipVoidPtrObject *)self)->size >= 0) return 0; PyErr_SetString(PyExc_IndexError, _SIP_MODULE_FQ_NAME ".voidptr object has an unknown size"); return -1; } /* * Check that a void pointer is writable. */ static int check_rw(PyObject *self) { if (((sipVoidPtrObject *)self)->rw) return 0; PyErr_SetString(PyExc_TypeError, "cannot modify a read-only " _SIP_MODULE_FQ_NAME ".voidptr object"); return -1; } /* * Check that an index is valid for a void pointer. */ static int check_index(PyObject *self, Py_ssize_t idx) { if (idx >= 0 && idx < ((sipVoidPtrObject *)self)->size) return 0; PyErr_SetString(PyExc_IndexError, "index out of bounds"); return -1; } /* * Raise an exception about a bad sub-script key. */ static void bad_key(PyObject *key) { PyErr_Format(PyExc_TypeError, "cannot index a " _SIP_MODULE_FQ_NAME ".voidptr object using '%s'", Py_TYPE(key)->tp_name); } /* * Check that the size of a value is the same as the size of the slice it is * replacing. */ static int check_slice_size(Py_ssize_t size, Py_ssize_t value_size) { if (value_size == size) return 0; PyErr_SetString(PyExc_ValueError, "cannot modify the size of a " _SIP_MODULE_FQ_NAME ".voidptr object"); return -1; } /* * Do the work of converting a void pointer. */ static PyObject *make_voidptr(void *voidptr, Py_ssize_t size, int rw) { sipVoidPtrObject *self; if (voidptr == NULL) { Py_INCREF(Py_None); return Py_None; } if ((self = PyObject_NEW(sipVoidPtrObject, &sipVoidPtr_Type)) == NULL) return NULL; self->voidptr = voidptr; self->size = size; self->rw = rw; return (PyObject *)self; } /* * Convert a Python object to the values needed to create a voidptr. */ static int vp_convertor(PyObject *arg, struct vp_values *vp) { void *ptr; Py_ssize_t size = -1; int rw = TRUE; if (arg == Py_None) { ptr = NULL; } else if (PyCapsule_CheckExact(arg)) { ptr = PyCapsule_GetPointer(arg, NULL); } else if (PyObject_TypeCheck(arg, &sipVoidPtr_Type)) { ptr = ((sipVoidPtrObject *)arg)->voidptr; size = ((sipVoidPtrObject *)arg)->size; rw = ((sipVoidPtrObject *)arg)->rw; } else if (PyObject_CheckBuffer(arg)) { Py_buffer view; if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0) return 0; ptr = view.buf; size = view.len; rw = !view.readonly; PyBuffer_Release(&view); } else { PyErr_Clear(); ptr = PyLong_AsVoidPtr(arg); if (PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "a single integer, Capsule, None, bytes-like object or another " _SIP_MODULE_FQ_NAME ".voidptr object is required"); return 0; } } vp->voidptr = ptr; vp->size = size; vp->rw = rw; return 1; } /* * Get a size possibly supplied as an argument, otherwise get it from the * object. Raise an exception if there was no size specified. */ static Py_ssize_t get_size_from_arg(sipVoidPtrObject *v, Py_ssize_t size) { /* Use the current size if one wasn't explicitly given. */ if (size < 0) size = v->size; if (size < 0) PyErr_SetString(PyExc_ValueError, "a size must be given or the " _SIP_MODULE_FQ_NAME ".voidptr object must have a size"); return size; }