File: pyste.txt

package info (click to toggle)
boost1.35 1.35.0-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 203,856 kB
  • ctags: 337,867
  • sloc: cpp: 938,683; xml: 56,847; ansic: 41,589; python: 18,999; sh: 11,566; makefile: 664; perl: 494; yacc: 456; asm: 353; csh: 6
file content (664 lines) | stat: -rw-r--r-- 21,602 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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 */
    }