summaryrefslogtreecommitdiff
path: root/libs/python/pyste/doc/pyste.txt
diff options
context:
space:
mode:
Diffstat (limited to 'libs/python/pyste/doc/pyste.txt')
-rw-r--r--libs/python/pyste/doc/pyste.txt664
1 files changed, 664 insertions, 0 deletions
diff --git a/libs/python/pyste/doc/pyste.txt b/libs/python/pyste/doc/pyste.txt
new file mode 100644
index 000000000..186a31cba
--- /dev/null
+++ b/libs/python/pyste/doc/pyste.txt
@@ -0,0 +1,664 @@
+[doc Pyste Documentation]
+
+[/ Copyright 2003 Bruno da Silva de Oliveira and Joel de Guzman.
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt) ]
+
+[def GCCXML [@http://www.gccxml.org GCCXML]]
+[def Boost.Python [@../../index.html Boost.Python]]
+
+[page Introduction]
+
+[h2 What is Pyste?]
+
+Pyste is a Boost.Python code generator. The user specifies the classes and
+functions to be exported using a simple ['interface file], which following the
+Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
+parse all the headers and extract the necessary information to automatically
+generate C++ code.
+
+[h2 Example]
+
+Let's borrow the class [^World] from the [@../../doc/tutorial/doc/exposing_classes.html tutorial]:
+
+ struct World
+ {
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+Here's the interface file for it, named [^world.pyste]:
+
+ Class("World", "world.h")
+
+and that's it!
+
+The next step is invoke Pyste in the command-line:
+
+[pre python pyste.py --module=hello world.pyste]
+
+this will create a file "[^hello.cpp]" in the directory where the command was
+run.
+
+Pyste supports the following features:
+
+* Functions
+* Classes
+* Class Templates
+* Virtual Methods
+* Overloading
+* Attributes
+* Enums (both "free" enums and class enums)
+* Nested Classes
+* Support for [^boost::shared_ptr] and [^std::auto_ptr]
+* Global Variables
+
+[page Running Pyste]
+
+To run Pyste, you will need:
+
+* Python 2.2, available at [@http://www.python.org python's website].
+* The great [@http://effbot.org elementtree] library, from Fredrik Lundh.
+* The excellent GCCXML, from Brad King.
+
+Installation for the tools is available in their respective webpages.
+
+[blurb
+[$theme/note.gif] GCCXML must be accessible in the PATH environment variable, so
+that Pyste can call it. How to do this varies from platform to platform.
+]
+
+[h2 Ok, now what?]
+
+Well, now let's fire it up:
+
+[pre
+'''
+>python pyste.py
+
+Pyste version 0.9.26
+
+Usage:
+ pyste [options] interface-files
+
+where options are:
+ --module=<name> The name of the module that will be generated;
+ defaults to the first interface filename, without
+ the extension.
+ -I <path> Add an include path
+ -D <symbol> Define symbol
+ --multiple Create various cpps, instead of only one
+ (useful during development)
+ --out=<name> Specify output filename (default: <module>.cpp)
+ in --multiple mode, this will be a directory
+ --no-using Do not declare "using namespace boost";
+ use explicit declarations instead
+ --pyste-ns=<name> Set the namespace where new types will be declared;
+ default is the empty namespace
+ --debug Writes the xml for each file parsed in the current
+ directory
+ --cache-dir=<dir> Directory for cache files (speeds up future runs)
+ --only-create-cache Recreates all caches (doesn't generate code).
+ --generate-main Generates the _main.cpp file (in multiple mode)
+ --file-list A file with one pyste file per line. Use as a
+ substitute for passing the files in the command
+ line.
+ -h, --help Print this help and exit
+ -v, --version Print version information
+
+'''
+]
+
+Options explained:
+
+The [^-I] and [^-D] are preprocessor flags, which are needed by GCCXML to parse
+the header files correctly and by Pyste to find the header files declared in the
+interface files.
+
+[^--out] names the output file (default: [^<module>.cpp]), or in multiple mode,
+names a output directory for the files (default: [^<module>]).
+
+[^--no-using] tells Pyste to don't declare "[^using namespace boost;]" in the
+generated cpp, using the namespace boost::python explicitly in all declarations.
+Use only if you're having a name conflict in one of the files.
+
+Use [^--pyste-ns] to change the namespace where new types are declared (for
+instance, the virtual wrappers). Use only if you are having any problems. By
+default, Pyste uses the empty namespace.
+
+[^--debug] will write in the current directory a xml file as outputted by GCCXML
+for each header parsed. Useful for bug reports.
+
+[^--file-list] names a file where each line points to a Pyste file. Use this instead
+to pass the pyste files if you have a lot of them and your shell has some command line
+size limit.
+
+The other options are explained below, in [@#multiple_mode [*Multiple Mode]] and
+[@#cache [*Cache]].
+
+[^-h, --help, -v, --version] are self-explaining, I believe. ;)
+
+So, the usage is simple enough:
+
+[pre >python pyste.py --module=mymodule file.pyste file2.pyste ...]
+
+will generate a file [^mymodule.cpp] in the same dir where the command was
+executed. Now you can compile the file using the same instructions of the
+[@../../doc/tutorial/doc/building_hello_world.html tutorial].
+
+[h2 Wait... how do I set those I and D flags?]
+
+Don't worry: normally GCCXML is already configured correctly for your plataform,
+so the search path to the standard libraries and the standard defines should
+already be set. You only have to set the paths to other libraries that your code
+needs, like Boost, for example.
+
+Plus, Pyste automatically uses the contents of the environment variable
+[^INCLUDE] if it exists. Visual C++ users should run the [^Vcvars32.bat] file,
+which for Visual C++ 6 is normally located at:
+
+ C:\Program Files\Microsoft Visual Studio\VC98\bin\Vcvars32.bat
+
+with that, you should have little trouble setting up the flags.
+
+[blurb [$theme/note.gif][*A note about Psyco][br][br]
+Although you don't have to install [@http://psyco.sourceforge.net/ Psyco] to
+use Pyste, if you do, Pyste will make use of it to speed up the wrapper
+generation. Speed ups of 30% can be achieved, so it's highly recommended.
+]
+
+
+[h2 Multiple Mode]
+
+The multiple mode is useful in large projects, where the presence of multiple
+classes in a single file makes the compilation unpractical (excessive memory
+usage, mostly).
+
+The solution is make Pyste generate multiple files, more specifically one cpp
+file for each Pyste file. This files will contain a function named after the
+file, for instance Export_MyPysteFile, which will contain all the code to export
+the classes, enums, etc. You can pass as much files as you want this way:
+
+[pre >python pyste.py --module=mymodule file1.pyste file2.pyste]
+
+This will create the files [^mymodule/file1.cpp] and [^mymodule/file2.cpp]. You
+can then later do:
+
+[pre >python pyste.py --module=mymodule file3.pyste]
+
+and [^mymodule/file3.cpp] will be generated.
+
+But compiling and linking this files won't be sufficient to generate your
+extension. You have to also generate a file named [^main.cpp]; call pyste with
+[*all] the Pyste files of your extension, and use the [^--generate-main] option:
+
+[pre >python pyste.py --module=mymodule --generate-main file1.pyste file2.pyste file3.pyste]
+
+Now compile and link all this files together and your extension is ready for
+use.
+
+[h2 Cache]
+
+Pyste now supports a form of cache, which is a way to speed up the code
+generation. Most of the time that Pyste takes to generate the code comes from
+having to execute GCCXML (since being a front-end to GCC, it has to compile the
+header files) and reading back the XML generated.
+
+When you use the [^--cache-dir=<dir>] option, Pyste will dump in the specified
+directory the generated XMLs to a file named after the Pyste file, with the
+extension [^.pystec]. The next time you run with this option, Pyste will use
+the cache, instead of calling GCCXML again:
+
+[pre >python pyste.py --module=mymodule --cache-dir=cache file1.pyste]
+
+Will generate [^file1.cpp] and [^cache/file1.pystec]. Next time you execute
+this command, the cache file will be used. Note that Pyste doesn't do any check
+to ensure that the cache is up to date, but you can configure your build system to do that for you.
+
+When you run Pyste with [^--only-create-cache], all the cache files will be
+created again, but no code will be generated.
+
+[page The Interface Files]
+
+The interface files are the heart of Pyste. The user creates one or more
+interface files declaring the classes and functions he wants to export, and then
+invokes Pyste passing the interface files to it. Pyste then generates a single
+cpp file with Boost.Python code, with all the classes and functions exported.
+
+Besides declaring the classes and functions, the user has a number of other
+options, like renaming e excluding classes and member functionis. Those are
+explained later on.
+
+[h2 Basics]
+
+Suppose we have a class and some functions that we want to expose to Python
+declared in the header [^hello.h]:
+
+ struct World
+ {
+ World(std::string msg): msg(msg) {}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+ enum choice { red, blue };
+
+ namespace test {
+
+ void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
+
+ }
+
+We create a file named [^hello.pyste] and create instances of the classes
+[^Function], [^Class] and [^Enum]:
+
+ Function("test::show", "hello.h")
+ Class("World", "hello.h")
+ Enum("choice", "hello.h")
+
+That will expose the class, the free function and the enum found in [^hello.h].
+
+[h2 Inheritance]
+
+Pyste automatically generates the correct code (specifying [^bases<>] in the
+[^class_] declaration) [*if] the Class() function that exports the base classes
+and their children are in the same Pyste file. If that's not the case, you have
+to indicate that there's a relationship between the Pyste files using the
+[^Import] function specifying the other Pyste file.
+
+Suppose we have two classes, [^A] and [^B], and A is a base class for B. We
+create two Pyste files:
+
+[^A.pyste]:
+
+ Class("A", "A.h")
+
+[^B.pyste]:
+
+ Import("A.pyste")
+ Class("B", "B.h")
+
+Note that we specify that [^B] needs to know about [^A] to be properly exported.
+
+[page:1 Renaming and Excluding]
+
+You can easily rename functions, classes, member functions, attributes, etc. Just use the
+function [^rename], like this:
+
+ World = Class("World", "hello.h")
+ rename(World, "IWorld")
+ show = Function("choice", "hello.h")
+ rename(show, "Show")
+
+You can rename member functions and attributes using this syntax:
+
+ rename(World.greet, "Greet")
+ rename(World.set, "Set")
+ choice = Enum("choice", "hello.h")
+ rename(choice.red, "Red")
+ rename(choice.blue, "Blue")
+
+You can exclude functions, classes, member functions, attributes, etc, in the same way,
+with the function [^exclude]:
+
+ exclude(World.greet)
+ exclude(World.msg)
+
+To access the operators of a class, access the member [^operator] like this
+(supposing that [^C] is a class being exported):
+
+ exclude(C.operator['+'])
+ exclude(C.operator['*'])
+ exclude(C.operator['<<'])
+
+The string inside the brackets is the same as the name of the operator in C++.[br]
+
+[h2 Virtual Member Functions]
+
+Pyste automatically generates wrappers for virtual member functions, but you may
+want to disable this behaviour (for performance reasons, for instance) if you do
+not plan to override the functions in Python. To do this, use the function
+[^final]:
+
+ C = Class('C', 'C.h')
+ final(C.foo) # C::foo is a virtual member function
+
+No virtual wrapper code will be generated for the virtual member function
+C::foo that way.
+
+[page:1 Policies]
+
+Even thought Pyste can identify various elements in the C++ code, like virtual
+member functions, attributes, and so on, one thing that it can't do is to
+guess the semantics of functions that return pointers or references. In this
+case, the user must manually specify the policy. Policies are explained in the
+[@../../doc/tutorial/doc/call_policies.html tutorial].
+
+The policies in Pyste are named exactly as in Boost.Python, only the syntax is
+slightly different. For instance, this policy:
+
+ return_internal_reference<1, with_custodian_and_ward<1, 2> >()
+
+becomes in Pyste:
+
+ return_internal_reference(1, with_custodian_and_ward(1, 2))
+
+The user can specify policies for functions and virtual member functions with
+the [^set_policy] function:
+
+ set_policy(f, return_internal_reference())
+ set_policy(C.foo, return_value_policy(manage_new_object))
+
+[blurb
+[$theme/note.gif] [*What if a function or member function needs a policy and
+the user doesn't set one?][br][br] If a function needs a policy and one
+was not set, Pyste will issue a error. The user should then go in the
+interface file and set the policy for it, otherwise the generated cpp won't
+compile.
+]
+
+[blurb
+[$theme/note.gif]
+Note that for functions that return [^const T&], the policy
+[^return_value_policy<copy_const_reference>()] wil be used by default, because
+that's normally what you want. You can change it to something else if you need
+to, though.
+]
+
+[page:1 Templates]
+
+Template classes can easily be exported too, but you can't export the template
+itself... you have to export instantiations of it! So, if you want to export a
+[^std::vector], you will have to export vectors of int, doubles, etc.
+
+Suppose we have this code:
+
+ template <class T>
+ struct Point
+ {
+ T x;
+ T y;
+ };
+
+And we want to export [^Point]s of int and double:
+
+ Point = Template("Point", "point.h")
+ Point("int")
+ Point("double")
+
+Pyste will assign default names for each instantiation. In this example, those
+would be "[^Point_int]" and "[^Point_double]", but most of the time users will want to
+rename the instantiations:
+
+ Point("int", "IPoint") // renames the instantiation
+ double_inst = Point("double") // another way to do the same
+ rename(double_inst, "DPoint")
+
+Note that you can rename, exclude, set policies, etc, in the [^Template] object
+like you would do with a [^Function] or a [^Class]. This changes affect all
+[*future] instantiations:
+
+ Point = Template("Point", "point.h")
+ Point("float", "FPoint") // will have x and y as data members
+ rename(Point.x, "X")
+ rename(Point.y, "Y")
+ Point("int", "IPoint") // will have X and Y as data members
+ Point("double", "DPoint") // also will have X and Y as data member
+
+If you want to change a option of a particular instantiation, you can do so:
+
+ Point = Template("Point", "point.h")
+ Point("int", "IPoint")
+ d_inst = Point("double", "DPoint")
+ rename(d_inst.x, "X") // only DPoint is affect by this renames,
+ rename(d_inst.y, "Y") // IPoint stays intact
+
+[blurb [$theme/note.gif] [*What if my template accepts more than one type?]
+[br][br]
+When you want to instantiate a template with more than one type, you can pass
+either a string with the types separated by whitespace, or a list of strings
+'''("int double" or ["int", "double"]''' would both work).
+]
+
+[page:1 Wrappers]
+
+Suppose you have this function:
+
+ std::vector<std::string> names();
+
+But you don't want to [@../../doc/v2/faq.html#question2 to export std::vector<std::string>],
+you want this function to return a python list of strings. Boost.Python has
+excellent support for things like that:
+
+ list names_wrapper()
+ {
+ list result;
+ // call original function
+ vector<string> v = names();
+ // put all the strings inside the python list
+ vector<string>::iterator it;
+ for (it = v.begin(); it != v.end(); ++it){
+ result.append(*it);
+ }
+ return result;
+ }
+
+ BOOST_PYTHON_MODULE(test)
+ {
+ def("names", &names_wrapper);
+ }
+
+Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper]
+function in a header named "[^test_wrappers.h]" and in the interface file:
+
+ Include("test_wrappers.h")
+ names = Function("names", "test.h")
+ set_wrapper(names, "names_wrapper")
+
+You can optionally declare the function in the interface file itself:
+
+ names_wrapper = Wrapper("names_wrapper",
+ """
+ list names_wrapper()
+ {
+ // code to call name() and convert the vector to a list...
+ }
+ """)
+ names = Function("names", "test.h")
+ set_wrapper(names, names_wrapper)
+
+The same mechanism can be used with member functions too. Just remember that
+the first parameter of wrappers for member functions is a pointer to the
+class, as in:
+
+ struct C
+ {
+ std::vector<std::string> names();
+ }
+
+ list names_wrapper(C* c)
+ {
+ // same as before, calling c->names() and converting result to a list
+ }
+
+And then in the interface file:
+
+ C = Class("C", "test.h")
+ set_wrapper(C.names, "names_wrapper")
+
+[blurb
+[$theme/note.gif]Even though Boost.Python accepts either a pointer or a
+reference to the class in wrappers for member functions as the first parameter,
+Pyste expects them to be a [*pointer]. Doing otherwise will prevent your
+code to compile when you set a wrapper for a virtual member function.
+]
+
+[page:1 Exporting An Entire Header]
+
+Pyste also supports a mechanism to export all declarations found in a header
+file. Suppose again our file, [^hello.h]:
+
+ struct World
+ {
+ World(std::string msg): msg(msg) {}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+ enum choice { red, blue };
+
+ void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
+
+You can just use the [^AllFromHeader] construct:
+
+ hello = AllFromHeader("hello.h")
+
+this will export all the declarations found in [^hello.h], which is equivalent
+to write:
+
+ Class("World", "hello.h")
+ Enum("choice", "hello.h")
+ Function("show", "hello.h")
+
+Note that you can still use the functions [^rename], [^set_policy], [^exclude], etc. Just access
+the members of the header object like this:
+
+ rename(hello.World.greet, "Greet")
+ exclude(hello.World.set, "Set")
+
+[blurb
+[$theme/note.gif] [*AllFromHeader is broken] in some cases. Until it is fixed,
+use at you own risk.
+]
+
+
+[page:1 Smart Pointers]
+
+Pyste for now has manual support for smart pointers. Suppose:
+
+ struct C
+ {
+ int value;
+ };
+
+ boost::shared_ptr<C> newC(int value)
+ {
+ boost::shared_ptr<C> c( new C() );
+ c->value = value;
+ return c;
+ }
+
+ void printC(boost::shared_ptr<C> c)
+ {
+ std::cout << c->value << std::endl;
+ }
+
+To make [^newC] and [^printC] work correctly, you have to tell Pyste that a
+convertor for [^boost::shared_ptr<C>] is needed.
+
+ C = Class('C', 'C.h')
+ use_shared_ptr(C)
+ Function('newC', 'C.h')
+ Function('printC', 'C.h')
+
+For [^std::auto_ptr]'s, use the function [^use_auto_ptr].
+
+This system is temporary, and in the future the converters will automatically be
+exported if needed, without the need to tell Pyste about them explicitly.
+
+[h2 Holders]
+
+If only the converter for the smart pointers is not enough and you need to
+specify the smart pointer as the holder for a class, use the functions
+[^hold_with_shared_ptr] and [^hold_with_auto_ptr]:
+
+ C = Class('C', 'C.h')
+ hold_with_shared_ptr(C)
+ Function('newC', 'C.h')
+ Function('printC', 'C.h')
+
+[page:1 Global Variables]
+
+To export global variables, use the [^Var] construct:
+
+ Var("myglobal", "foo.h")
+
+Beware of non-const global variables: changes in Python won't reflect in C++!
+If you really must change them in Python, you will have to write some accessor
+functions, and export those.
+
+
+[page:1 Adding New Methods]
+
+Suppose that you want to add a function to a class, turning it into a member
+function:
+
+ struct World
+ {
+ void set(std::string msg) { this->msg = msg; }
+ std::string msg;
+ };
+
+ std::string greet(World& w)
+ {
+ return w.msg;
+ }
+
+Here, we want to make [^greet] work as a member function of the class [^World]. We do
+that using the [^add_method] construct:
+
+ W = Class("World", "hello.h")
+ add_method(W, "greet")
+
+Notice also that then you can rename it, set its policy, just like a regular
+member function:
+
+ rename(W.greet, 'Greet')
+
+Now from Python:
+
+ >>> import hello
+ >>> w = hello.World()
+ >>> w.set('Ni')
+ >>> w.greet()
+ 'Ni'
+ >>> print 'Oh no! The knights who say Ni!'
+ Oh no! The knights who say Ni!
+
+
+[page:1 Inserting Code]
+
+You can insert arbitrary code in the generated cpps, just use the functions
+[^declaration_code] and [^module_code]. This will insert the given string in the
+respective sections. Example:
+
+ # file A.pyste
+ Class("A", "A.h")
+ declaration_code("/* declaration_code() comes here */\n")
+ module_code("/* module_code() comes here */\n")
+
+Will generate:
+
+ // Includes ====================================================================
+ #include <boost/python.hpp>
+
+ // Using =======================================================================
+ using namespace boost::python;
+
+ // Declarations ================================================================
+
+ /* declaration_code() comes here */
+
+ // Module ======================================================================
+ BOOST_PYTHON_MODULE(A)
+ {
+ class_< A >("A", init< >())
+ .def(init< const A& >())
+ ;
+
+ /* module_code() comes here */
+ }