Author: | Greg Couch |
---|---|
Email: | gregc@cgl.ucsf.edu |
Lab: | UCSF Computer Graphics Lab |
Copyright: | Copyright (c) 1996-2003 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, distribution and/or use acknowledge that the software was developed by the Computer Graphics Laboratory, University of California, San Francisco. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE. |
wrappy reads annotated C++ header files and generates a Python module containing a Python class or a Python type for each C++ class. Global functions are placed in the module as well.
C++ classes that subclass from otf::WrapPy<class> default to generating Python classes. C++ structs default to generating Python types. These defaults may be overridden by class annotations (see below). You should include <otf/WrapPy.h> to get the otf::WrapPy template base class.
Static C++ member functions are made in to Python module functions. The names are prepended with the C++ class name and an underscore. C++ class constants for Python types are likewise placed in the Python module. C++ constants in Python classes are accessed as part of the class.
-d | Generate a wrappy_doc dictionary in the module with information about the various classes and types in module. |
-e tag | Put the given tag before every exportable symbol in the generated header files. The tag is used for Windows OSes dynamic libraries. |
-g minimum | Set the minimum number of names in a class (attributes, member functions) needed to use a perfect hash function (from the gperf(1) program). |
-h file | Add extra header file to module.h |
-i token | Ignore token (e.g., a tag from a different module). |
-m module-name | Name of the Python module generated. |
-n | Don't generate any output, just check the input file(s). |
-N namespace | Place the generated code (except for init module!) into the given namespace. |
-s class-name | Generate code for a single class. The special name __module__ can be given to get the module level code. |
-w | Turn on warnings about get/set attribute types not matching. Not all mismatches are errors. |
Deprecated: |
---|
-B | Turn on fixes for Borland 5.[45] compilers (-DIT). |
-D | Turn on explicit naming of destructors. |
-I | Turn off inline in one case. |
-T | Turn on explict naming of template functions. |
Wrappy parses C++ as simply as it can. Consequently, some legal C++ header files can not be parsed correctly.
- Global/namespace variables are not supported.
- All function arguments must have a parameter name -- the name is used as the Python argument keyword.
- Overloaded functions are supported but they can't have default arguments (this may change, the problem is interplay with keyword arguments).
- Only one declaration per type (e.g., no int x, y;).
- No combination typedef and struct declaration (i.e., separate typedef struct _t { ... } T; into struct _t { ... } and typedef struct _t T;)
- No using namespace ``|NAME|;``.
- Virtual functions repeated in subclasses will generate another entry point in the subclass.
- Private base classes become public in Python.
Most other restrictions are bugs.
C++ class public member variables are made into Python class/type attributes.
Paired class member functions are collapsed into Python attributes as well: [Gg]etNAME/[Ss]etNAME creates an NAME attribute. Likewise for NAME/[Ss]etNAME.
If you have only one half of the paired member functions, it can still be an attribute if it annotated as such (see below).
All annotations are placed in C/C++ comments.
Arguments that are used return values must be annotated. Typically, these annotations are placed in the argument list as C-style comments so they be placed inline:
- /*IN*/
- This argument is input to the function (default).
- /*OUT*/
- This argument is output from the function.
- /*INOUT*/
- This argument is used for input to and output from the function.
- // #include filename
- Use filename as include file for class instead of the file the class definition was read from.
- // WRAP CLASS
- Generate a Python type or class for this C++ class even though it is in another namespace.
- // PYTHON CLASS
- Generate a Python class for this C++ class.
- // PYTHON TYPE
- Generate a Python type for this C++ class.
- // ABSTRACT
- Don't create a Python constructor for this C++ class. Don't generate a Python type for this class, but allow function arguments and return values to be of this class. Good for C++ abstract base classes.
- // NUMBER METHODS
- Generate Python interface for operator+, operator+, etc.
- // SEQUENCE METHODS
- Generate Python interface for len: size(), concat: operator+(?), repeat: operator*(?), getitem: operator[](int), setitem: ?& operator[](int). delitem is not supported. getslice and setslice are not supported. Python 1.6's contains is not supported.
- // MAPPING METHODS
- Generate Python interface for len: size(), getitem: operator[](?), setitem: ?& operator[](?). delitem is not supported.
- // BUFFER PROCS
- Recognized but not implemented.
- // DON'T CACHE
- Don't cache attributes of this C++ class.
These annotations also go in the C++ class definition.
- // ATTRIBUTE: name
- Make the corresponding get/set function to name an attribute. (Not needed if both a get and a set function are present.)
- // READONLY: name
- Ignore the set function for named attribute.
- // WRITEONLY: name
- Ignore the get function for named attribute.
- // WEAKREF: name
- Don't cache references for named attribute.
- // #include filename
- Use filename as include file for following classes instead of the file the class definition was read from.
wrappy understands that it should ignore declarations within:
#ifndef WrapPy
- or
- #if 0
and ending with an #else clause or #endif. All of the declarations inside the #if*/(#else|#endif) must parse. #elif clauses are recognized, but not recommended, because the contents of all clauses are added to the parsed declarations.
Nested #if*'s are recognized.
Containers are not supported as input to functions.
using directive only takes names, not function prototypes;
Constructor try blocks are not recognized.
Function exception specifications are not used.
Function pointers are not supported.
Wrappy finds the operator<<(?, type) form and trys to create a __rlshift__ operator for unwrapped ?.
All of the clauses of an #if``* must be in the same scope (*e.g.*, if the ``#endif is inside a class declaration, then the corresponding #if* must be too).
And more....
Example command line usage:
wrappy -g 4 -N example -n example example.h
Example input file:
namespace example { class Info { // #include "Example.h" public: .... }; typedef std::vector<Info *> InfoList; class DB { // #include "Example.h" public: // infos will be an attribute void infos(/*OUT*/ const InfoList *infolist) const; void setInfos(const InfoList &infolist); };