# PyPy[standalone-howto]

PyPy[standalone-howto]
news getting-started documentation svn issues contact EU/project

# HOWTO: compile RPython code into a standalone executable

(NOTE: you should first read the FAQ entries about Using the PyPy translation tool chain. This document is a quick introduction to the interactive way to compile your own RPython code. Keep in mind though that if you write a larger RPython program, the best and most flexible way to compile it is not as described below, but by writing a target file as described in the FAQ entries.)

First, see the note above. Next, understand the restrictions on RPython code. Pay close attention to the description of tuples and dicts.

Take this example program:

    import os

    def main(argv):
        os.write(1, "Hello world!\n")

        return 0

To compile:

    from pypy.translator.interactive import Translation
    t = Translation(main, standalone=True, gc='ref')

    t.source(backend='c')
    path = t.compile()
    print path

The path is the location of the executable.

To see the translation in motion, try removing the `argv` argument to main, or the `return 0`.

Type inference happens in the Annotator. Keep this in mind as you write RPython code. After annotation the low level code generation (the implementation of the types) happens in the RTyper.

These steps can be spelled out explicitly:

    t.annotate()
    t.rtype()
    t.source(backend='c')
    path = t.compile()

After the `annotate()` or `rtype()` call you can view the resulting flow graph with a pygame/dot based graphing tool:

    t.annotate()
    t.view()
    t.rtype()
    t.view()

Here are some debugging tips:

- make sure the program runs before you try and compile it. The semantics of RPython compiled code should be the same as regular python.
- try assert'ing things in your code, for example `assert isinstance(num, int)`, this can provide hints to the translation process that can help pinpoint the problem.

RPython is tricky!

Take this example:

    def abs(num):
        if num < 0:
            num = -num
        return num

If you want to use this function with different argument types (eg. `int` and `float`) the translation will fail. In order to generate a different function for each argument type we need to set an attribute:

    abs._annspecialcase_ = "specialize:argtype(0)"

As another example:

    def sum(l):
        total = 0
        for v in l:
            total += v
        return total

    sum._annspecialcase_ = "specialize:argtype(0)"

Now we can sum with different kinds of lists, eg. `sum([1,2,3])` and `sum([1.0,2.0,3.0])`.

Here is an example of using rctypes:

    import ctypes
    from ctypes import c_int, c_char_p
    import pypy.rpython.rctypes.implementation

    libc = ctypes.cdll.LoadLibrary('libc.so.6')

    write = libc.write
    write.argtypes = [c_int, c_char_p, c_int]
    write.restype = c_int

    def main(argv):

        msg = "Hello world!\n"
        write(1, msg, len(msg))

        return 0

PyPy implements the ctypes semantics as the corresponding native c-code equivalents.