wrapping_CPlusPlus.rst 23 KB
Newer Older
Robert Bradshaw's avatar
Robert Bradshaw committed
1 2 3 4 5
.. highlight:: cython

.. _wrapping-cplusplus:

********************************
Stefan Behnel's avatar
Stefan Behnel committed
6
Using C++ in Cython
Robert Bradshaw's avatar
Robert Bradshaw committed
7 8 9 10 11
********************************

Overview
=========

12
Cython has native support for most of the C++ language.  Specifically:
13 14

* C++ objects can now be dynamically allocated with ``new`` and ``del`` keywords.
15
* C++ objects can be stack-allocated.
16
* C++ classes can be declared with the new keyword ``cppclass``.
17
* Templated classes and functions are supported.
18 19
* Overloaded functions are supported.
* Overloading of C++ operators (such as operator+, operator[],...) is supported.
Robert Bradshaw's avatar
Robert Bradshaw committed
20 21

Procedure Overview
22
-------------------
23
The general procedure for wrapping a C++ file can now be described as follows:
Robert Bradshaw's avatar
Robert Bradshaw committed
24

25 26 27 28 29 30 31 32 33
* Specify C++ language in :file:`setup.py` script or locally in a source file.
* Create one or more .pxd files with ``cdef extern from`` blocks and
  (if existing) the C++ namespace name.  In these blocks,

  * declare classes as ``cdef cppclass`` blocks
  * declare public names (variables, methods and constructors)

* Write an extension modules, ``cimport`` from the .pxd file and use
  the declarations.
34 35 36

A simple Tutorial
==================
Robert Bradshaw's avatar
Robert Bradshaw committed
37 38

An example C++ API
39
-------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
40 41 42 43 44 45 46

Here is a tiny C++ API which we will use as an example throughout this
document. Let's assume it will be in a header file called
:file:`Rectangle.h`:

.. sourcecode:: c++

47 48 49 50
    namespace shapes {
        class Rectangle {
        public:
            int x0, y0, x1, y1;
51
            Rectangle();
52 53 54
            Rectangle(int x0, int y0, int x1, int y1);
            ~Rectangle();
            int getArea();
David Nogueira's avatar
David Nogueira committed
55
            void getSize(int* width, int* height);
56 57 58
            void move(int dx, int dy);
        };
    }
59

60 61 62 63 64 65
and the implementation in the file called :file:`Rectangle.cpp`:

.. sourcecode:: c++

    #include "Rectangle.h"

Robert Bradshaw's avatar
Robert Bradshaw committed
66
    namespace shapes {
67

68 69
      Rectangle::Rectangle() { }

Robert Bradshaw's avatar
Robert Bradshaw committed
70 71 72 73 74 75 76 77 78 79 80 81 82
        Rectangle::Rectangle(int X0, int Y0, int X1, int Y1) {
            x0 = X0;
            y0 = Y0;
            x1 = X1;
            y1 = Y1;
        }

        Rectangle::~Rectangle() { }

        int Rectangle::getArea() {
            return (x1 - x0) * (y1 - y0);
        }

83
        void Rectangle::getSize(int *width, int *height) {
84 85
            (*width) = x1 - x0;
            (*height) = y1 - y0;
86 87
        }

Robert Bradshaw's avatar
Robert Bradshaw committed
88 89 90 91 92 93
        void Rectangle::move(int dx, int dy) {
            x0 += dx;
            y0 += dy;
            x1 += dx;
            y1 += dy;
        }
94

95 96
    }

Robert Bradshaw's avatar
Robert Bradshaw committed
97 98 99
This is pretty dumb, but should suffice to demonstrate the steps involved.

Specify C++ language in setup.py
100
---------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
101

102 103 104
The best way to build Cython code from :file:`setup.py` scripts is the
``cythonize()`` function.  To make Cython generate and compile C++ code
with distutils, you just need to pass the option ``language="c++"``::
Robert Bradshaw's avatar
Robert Bradshaw committed
105

106
   from distutils.core import setup
107
   from Cython.Build import cythonize
108

109 110 111 112 113
   setup(ext_modules = cythonize(
              "rect.pyx",                 # our Cython source
              sources=["Rectangle.cpp"],  # additional source file(s)
              language="c++",             # generate C++ code
         ))
Robert Bradshaw's avatar
Robert Bradshaw committed
114

115 116
Cython will generate and compile the :file:`rect.cpp` file (from the
:file:`rect.pyx`), then it will compile :file:`Rectangle.cpp`
117
(implementation of the ``Rectangle`` class) and link both objects files
118 119
together into :file:`rect.so`, which you can then import in Python using
``import rect`` (if you forget to link the :file:`Rectangle.o`, you will
120 121
get missing symbols while importing the library in Python).

122 123 124 125
Note that the ``language`` option has no effect on user provided Extension
objects that are passed into ``cythonize()``.  It is only used for modules
found by file name (as in the example above).

126 127 128 129 130 131 132 133 134
The ``cythonize()`` function in Cython versions up to 0.21 does not
recognize the ``language`` option and it needs to be specified as an
option to an :class:`Extension` that describes your extension and that
is then handled by ``cythonize()`` as follows::

   from distutils.core import setup, Extension
   from Cython.Build import cythonize

   setup(ext_modules = cythonize(Extension(
Jakub Wilk's avatar
Jakub Wilk committed
135
              "rect",                                # the extension name
136 137 138 139 140
              sources=["rect.pyx", "Rectangle.cpp"], # the Cython source and
                                                     # additional C++ source files
              language="c++",                        # generate and compile C++ code
         )))

141
The options can also be passed directly from the source file, which is
142 143 144
often preferable (and overrides any global option).  Starting with
version 0.17, Cython also allows to pass external source files into the
``cythonize()`` command this way.  Here is a simplified setup.py file::
Robert Bradshaw's avatar
Robert Bradshaw committed
145

146 147 148 149 150 151 152 153 154 155
   from distutils.core import setup
   from Cython.Build import cythonize

   setup(
       name = "rectangleapp",
       ext_modules = cythonize('*.pyx'),
   )

And in the .pyx source file, write this into the first comment block, before
any source code, to compile it in C++ mode and link it statically against the
Jakub Wilk's avatar
Jakub Wilk committed
156
:file:`Rectangle.cpp` code file::
157 158 159 160 161 162 163 164

   # distutils: language = c++
   # distutils: sources = Rectangle.cpp

To compile manually (e.g. using ``make``), the ``cython`` command-line
utility can be used to generate a C++ ``.cpp`` file, and then compile it
into a python extension.  C++ mode for the ``cython`` command is turned
on with the ``--cplus`` option.
165 166 167

Declaring a C++ class interface
--------------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
168 169 170 171 172

The procedure for wrapping a C++ class is quite similar to that for wrapping
normal C structs, with a couple of additions. Let's start here by creating the
basic ``cdef extern from`` block::

173
    cdef extern from "Rectangle.h" namespace "shapes":
Robert Bradshaw's avatar
Robert Bradshaw committed
174

175
This will make the C++ class def for Rectangle available. Note the namespace declaration.
Robert Bradshaw's avatar
Robert Bradshaw committed
176
Namespaces are simply used to make the fully qualified name of the object, and can be nested (e.g. ``"outer::inner"``) or even refer to classes (e.g. ``"namespace::MyClass`` to declare static members on MyClass).
Robert Bradshaw's avatar
Robert Bradshaw committed
177

178 179
Declare class with cdef cppclass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Robert Bradshaw's avatar
Robert Bradshaw committed
180

181 182
Now, let's add the Rectangle class to this extern from block - just copy the
class name from Rectangle.h and adjust for Cython syntax, so now it becomes::
Robert Bradshaw's avatar
Robert Bradshaw committed
183

184 185
    cdef extern from "Rectangle.h" namespace "shapes":
        cdef cppclass Rectangle:
186

187 188
Add public attributes
^^^^^^^^^^^^^^^^^^^^^^
Robert Bradshaw's avatar
Robert Bradshaw committed
189

190
We now need to declare the attributes and methods for use on Cython::
Robert Bradshaw's avatar
Robert Bradshaw committed
191

192 193
    cdef extern from "Rectangle.h" namespace "shapes":
        cdef cppclass Rectangle:
194
            Rectangle() except +
195
            Rectangle(int, int, int, int) except +
Robert Bradshaw's avatar
Robert Bradshaw committed
196
            int x0, y0, x1, y1
197
            int getArea()
198
            void getSize(int* width, int* height)
199
            void move(int, int)
Robert Bradshaw's avatar
Robert Bradshaw committed
200

201 202 203 204 205 206
Note that the constructor is declared as "except +".  If the C++ code or
the initial memory allocation raises an exception due to a failure, this
will let Cython safely raise an appropriate Python exception instead
(see below).  Without this declaration, C++ exceptions originating from
the constructor will not be handled by Cython.

207 208
Declare a var with the wrapped C++ class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Robert Bradshaw's avatar
Robert Bradshaw committed
209

Robert Bradshaw's avatar
Robert Bradshaw committed
210
Now, we use cdef to declare a var of the class with the C++ ``new`` statement::
Robert Bradshaw's avatar
Robert Bradshaw committed
211

212
    rec_ptr = new Rectangle(1, 2, 3, 4)
213
    try:
214
        recArea = rec_ptr.getArea()
215 216
        ...
    finally:
217
        del rec_ptr     # delete heap allocated object
Robert Bradshaw's avatar
Robert Bradshaw committed
218

219 220
It's also possible to declare a stack allocated object, as long as it has
a "default" constructor::
Robert Bradshaw's avatar
Robert Bradshaw committed
221

222 223 224
    cdef extern from "Foo.h":
        cdef cppclass Foo:
            Foo()
Robert Bradshaw's avatar
Robert Bradshaw committed
225

226 227 228
    def func():
        cdef Foo foo
        ...
Robert Bradshaw's avatar
Robert Bradshaw committed
229

230
Note that, like C++, if the class has only one constructor and it
231
is a nullary one, it's not necessary to declare it.
Robert Bradshaw's avatar
Robert Bradshaw committed
232 233

Create Cython wrapper class
234
----------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
235

236 237 238
At this point, we have exposed into our pyx file's namespace the interface
of the C++ Rectangle type.  Now, we need to make this accessible from
external Python code (which is our whole point).
Robert Bradshaw's avatar
Robert Bradshaw committed
239 240

Common programming practice is to create a Cython extension type which
241
holds a C++ instance as an attribute and create a bunch of
Robert Bradshaw's avatar
Robert Bradshaw committed
242 243
forwarding methods. So we can implement the Python extension type as::

244
    cdef class PyRectangle:
245
        cdef Rectangle c_rect      # hold a C++ instance which we're wrapping
Robert Bradshaw's avatar
Robert Bradshaw committed
246
        def __cinit__(self, int x0, int y0, int x1, int y1):
247 248 249
            self.c_rect = Rectangle(x0, y0, x1, y1)
        def get_area(self):
            return self.c_rect.getArea()
David Nogueira's avatar
David Nogueira committed
250 251
        def get_size(self):
            cdef int width, height
252 253
            self.c_rect.getSize(&width, &height)
            return width, height
Robert Bradshaw's avatar
Robert Bradshaw committed
254
        def move(self, dx, dy):
255
            self.c_rect.move(dx, dy)
Robert Bradshaw's avatar
Robert Bradshaw committed
256 257

And there we have it. From a Python perspective, this extension type will look
258 259 260 261
and feel just like a natively defined Rectangle class.
It should be noted that

If you want to give
Robert Bradshaw's avatar
Robert Bradshaw committed
262 263
attribute access, you could just implement some properties::

264 265 266 267 268 269 270
    @property
    def x0(self):
        return self.c_rect.x0

    @x0.setter
    def x0(self):
        def __set__(self, x0): self.c_rect.x0 = x0
Robert Bradshaw's avatar
Robert Bradshaw committed
271 272
    ...

273 274 275 276 277 278 279
Cython initializes C++ class attributes of a cdef class using the nullary constructor.
If the class you're wrapping does not have a nullary constructor, you must store a pointer
to the wrapped class and manually allocate and deallocate it.
A convienient and safe place to do so is in the `__cinit__` and `__dealloc__` methods
which are guaranteed to be called exactly once upon creation and deletion of the Python
instance.

Stefan Behnel's avatar
Stefan Behnel committed
280 281
::

282 283 284 285 286 287 288 289
    cdef class PyRectangle:
        cdef Rectangle* c_rect      # hold a pointer to the C++ instance which we're wrapping
        def __cinit__(self, int x0, int y0, int x1, int y1):
            self.c_rect = new Rectangle(x0, y0, x1, y1)
        def __dealloc__(self):
            del self.c_rect
        ...

290 291 292
If you prefer giving the same name to the wrapper as the C++ class, see the
section on :ref:`resolving naming conflicts <resolve-conflicts>`.

Robert Bradshaw's avatar
Robert Bradshaw committed
293

294 295
Advanced C++ features
======================
Robert Bradshaw's avatar
Robert Bradshaw committed
296

297
We describe here all the C++ features that were not discussed in the above tutorial.
Robert Bradshaw's avatar
Robert Bradshaw committed
298 299 300 301

Overloading
------------

302 303
Overloading is very simple. Just declare the method with different parameters
and use any of them::
Robert Bradshaw's avatar
Robert Bradshaw committed
304

305 306 307 308 309 310
    cdef extern from "Foo.h":
        cdef cppclass Foo:
            Foo(int)
            Foo(bool)
            Foo(int, bool)
            Foo(int, int)
Robert Bradshaw's avatar
Robert Bradshaw committed
311

312 313
Overloading operators
----------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
314

Robert Bradshaw's avatar
Robert Bradshaw committed
315
Cython uses C++ naming for overloading operators::
Robert Bradshaw's avatar
Robert Bradshaw committed
316

317 318 319
    cdef extern from "foo.h":
        cdef cppclass Foo:
            Foo()
Robert Bradshaw's avatar
Robert Bradshaw committed
320 321 322
            Foo operator+(Foo)
            Foo operator-(Foo)
            int operator*(Foo)
323
            int operator/(int)
Robert Bradshaw's avatar
Robert Bradshaw committed
324

Robert Bradshaw's avatar
Robert Bradshaw committed
325
    cdef Foo foo = new Foo()
Robert Bradshaw's avatar
Robert Bradshaw committed
326

Robert Bradshaw's avatar
Robert Bradshaw committed
327 328
    foo2 = foo + foo
    foo2 = foo - foo
Robert Bradshaw's avatar
Robert Bradshaw committed
329

Robert Bradshaw's avatar
Robert Bradshaw committed
330 331
    x = foo * foo2
    x = foo / 1
Robert Bradshaw's avatar
Robert Bradshaw committed
332

Robert Bradshaw's avatar
Robert Bradshaw committed
333 334 335 336 337 338 339 340 341
Note that if one has *pointers* to C++ objects, dereferencing must be done
to avoid doing pointer arithmetic rather than arithmetic on the objects
themselves::

    cdef Foo* foo_ptr = new Foo()
    foo = foo_ptr[0] + foo_ptr[0]
    x = foo_ptr[0] / 2

    del foo_ptr
342 343 344 345


Nested class declarations
--------------------------
346 347
C++ allows nested class declaration. Class declarations can also be
nested in Cython::
348 349 350 351 352 353 354 355 356 357 358 359 360 361

    cdef extern from "<vector>" namespace "std":
        cdef cppclass vector[T]:
            cppclass iterator:
                T operator*()
                iterator operator++()
                bint operator==(iterator)
                bint operator!=(iterator)
            vector()
            void push_back(T&)
            T& operator[](int)
            T& at(int)
            iterator begin()
            iterator end()
362

363
    cdef vector[int].iterator iter  #iter is declared as being of type vector<int>::iterator
364

365 366 367 368 369
Note that the nested class is declared with a ``cppclass`` but without a ``cdef``.

C++ operators not compatible with Python syntax
------------------------------------------------

370 371 372 373 374
Cython try to keep a syntax as close as possible to standard Python.
Because of this, certain C++ operators, like the preincrement ``++foo``
or the dereferencing operator ``*foo`` cannot be used with the same
syntax as C++. Cython provides functions replacing these operators in
a special module ``cython.operator``. The functions provided are:
375

376
* ``cython.operator.dereference`` for dereferencing. ``dereference(foo)``
377
  will produce the C++ code ``*(foo)``
378
* ``cython.operator.preincrement`` for pre-incrementation. ``preincrement(foo)``
379 380 381 382
  will produce the C++ code ``++(foo)``.
  Similarly for ``predecrement``, ``postincrement`` and ``postdecrement``.
* ``cython.operator.comma`` for the comma operator. ``comma(a, b)``
  will produce the C++ code ``((a), (b))``.
383

384 385 386
These functions need to be cimported. Of course, one can use a
``from ... cimport ... as`` to have shorter and more readable functions.
For example: ``from cython.operator cimport dereference as deref``.
387

388 389 390
For completeness, it's also worth mentioning ``cython.operator.address``
which can also be written ``&foo``.

391 392 393 394 395
Templates
----------

Cython uses a bracket syntax for templating. A simple example for wrapping C++ vector::

396 397
    # import dereference and increment operators
    from cython.operator cimport dereference as deref, preincrement as inc
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

    cdef extern from "<vector>" namespace "std":
        cdef cppclass vector[T]:
            cppclass iterator:
                T operator*()
                iterator operator++()
                bint operator==(iterator)
                bint operator!=(iterator)
            vector()
            void push_back(T&)
            T& operator[](int)
            T& at(int)
            iterator begin()
            iterator end()

    cdef vector[int] *v = new vector[int]()
    cdef int i
    for i in range(10):
        v.push_back(i)

    cdef vector[int].iterator it = v.begin()
    while it != v.end():
        print deref(it)
        inc(it)

    del v

425 426 427
Multiple template parameters can be defined as a list, such as ``[T, U, V]``
or ``[int, bool, char]``.  Optional template parameters can be indicated
by writing ``[T, U, V=*]``.  In the event that Cython needs to explicitly
Robert Bradshaw's avatar
Robert Bradshaw committed
428 429 430
reference the type of a default template parameter for an incomplete template
instantiation, it will write ``MyClass<T, U>::V``, so if the class provides
a typedef for its template parameters it is preferable to use that name here.
431 432 433


Template functions are defined similarly to class templates, with
434 435
the template parameter list following the function name::

Robert Bradshaw's avatar
Robert Bradshaw committed
436
    cdef extern from "<algorithm>" namespace "std":
437 438 439 440 441
        T max[T](T a, T b)

    print max[long](3, 4)
    print max(1.5, 2.5)  # simple template argument deduction

442 443 444 445

Standard library
-----------------

446 447 448
Most of the containers of the C++ Standard Library have been declared
in pxd files located in ``/Cython/Includes/libcpp``.  These containers
are: deque, list, map,  pair,  queue,  set,  stack,  vector.
449 450 451 452 453 454 455 456 457 458 459

For example::

    from libcpp.vector cimport vector

    cdef vector[int] vect
    cdef int i
    for i in range(10):
        vect.push_back(i)
    for i in range(10):
        print vect[i]
460

461 462
The pxd files in ``/Cython/Includes/libcpp`` also work as good examples on
how to declare C++ classes.
Robert Bradshaw's avatar
Robert Bradshaw committed
463

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
Since Cython 0.17, the STL containers coerce from and to the
corresponding Python builtin types.  The conversion is triggered
either by an assignment to a typed variable (including typed function
arguments) or by an explicit cast, e.g.::

    from libcpp.string cimport string
    from libcpp.vector cimport vector

    cdef string s = py_bytes_object
    print(s)
    cpp_string = <string> py_unicode_object.encode('utf-8')

    cdef vector[int] vect = xrange(1, 10, 2)
    print(vect)              # [1, 3, 5, 7, 9]

    cdef vector[string] cpp_strings = b'ab cd ef gh'.split()
Stefan Behnel's avatar
Stefan Behnel committed
480
    print(cpp_strings[1])   # b'cd'
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502

The following coercions are available:

+------------------+----------------+-----------------+
| Python type =>   | *C++ type*     | => Python type  |
+==================+================+=================+
| bytes            | std::string    | bytes           |
+------------------+----------------+-----------------+
| iterable         | std::vector    | list            |
+------------------+----------------+-----------------+
| iterable         | std::list      | list            |
+------------------+----------------+-----------------+
| iterable         | std::set       | set             |
+------------------+----------------+-----------------+
| iterable (len 2) | std::pair      | tuple (len 2)   |
+------------------+----------------+-----------------+

All conversions create a new container and copy the data into it.
The items in the containers are converted to a corresponding type
automatically, which includes recursively converting containers
inside of containers, e.g. a C++ vector of maps of strings.

503 504 505 506 507 508 509 510
Iteration over stl containers (or indeed any class with ``begin()`` and
``end()`` methods returning an object supporting incrementing, dereferencing,
and comparison) is supported via the ``for .. in`` syntax (including in list
comprehensions).  For example, one can write::

    cdef vector[int] v = ...
    for value in v:
        f(value)
511
    return [x*x for x in v if x % 2 == 0]
512

513 514 515
If the loop target variable is unspecified, an assignment from type
``*container.begin()`` is used for :ref:`type inference <compiler-directives>`.

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

Simplified wrapping with default constructor
--------------------------------------------

If your extension type instantiates a wrapped C++ class using the default
constructor (not passing any arguments), you may be able to simplify the
lifecycle handling by tying it directly to the lifetime of the Python wrapper
object.  Instead of a pointer attribute, you can declare an instance::

    cdef class VectorStack:
        cdef vector[int] v

        def push(self, x):
            self.v.push_back(x)

        def pop(self):
            if self.v.empty():
                raise IndexError()
            x = self.v.back()
            self.v.pop_back()
            return x

Cython will automatically generate code that instantiates the C++ object
instance when the Python object is created and deletes it when the Python
object is garbage collected.



Robert Bradshaw's avatar
Robert Bradshaw committed
544
Exceptions
545
-----------
Robert Bradshaw's avatar
Robert Bradshaw committed
546 547 548 549 550 551 552 553

Cython cannot throw C++ exceptions, or catch them with a try-except statement,
but it is possible to declare a function as potentially raising an C++
exception and converting it into a Python exception. For example, ::

    cdef extern from "some_file.h":
        cdef int foo() except +

554 555 556 557 558 559 560 561 562 563 564
This will translate try and the C++ error into an appropriate Python exception.
The translation is performed according to the following table
(the ``std::`` prefix is omitted from the C++ identifiers):

+-----------------------+---------------------+
| C++                   | Python              |
+=======================+=====================+
| ``bad_alloc``         | ``MemoryError``     |
+-----------------------+---------------------+
| ``bad_cast``          | ``TypeError``       |
+-----------------------+---------------------+
565 566
| ``bad_typeid``        | ``TypeError``       |
+-----------------------+---------------------+
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
| ``domain_error``      | ``ValueError``      |
+-----------------------+---------------------+
| ``invalid_argument``  | ``ValueError``      |
+-----------------------+---------------------+
| ``ios_base::failure`` | ``IOError``         |
+-----------------------+---------------------+
| ``out_of_range``      | ``IndexError``      |
+-----------------------+---------------------+
| ``overflow_error``    | ``OverflowError``   |
+-----------------------+---------------------+
| ``range_error``       | ``ArithmeticError`` |
+-----------------------+---------------------+
| ``underflow_error``   | ``ArithmeticError`` |
+-----------------------+---------------------+
| (all others)          | ``RuntimeError``    |
+-----------------------+---------------------+

The ``what()`` message, if any, is preserved. Note that a C++
``ios_base_failure`` can denote EOF, but does not carry enough information
for Cython to discern that, so watch out with exception masks on IO streams. ::
Robert Bradshaw's avatar
Robert Bradshaw committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600

    cdef int bar() except +MemoryError

This will catch any C++ error and raise a Python MemoryError in its place.
(Any Python exception is valid here.) ::

    cdef int raise_py_error()
    cdef int something_dangerous() except +raise_py_error

If something_dangerous raises a C++ exception then raise_py_error will be
called, which allows one to do custom C++ to Python error "translations." If
raise_py_error does not actually raise an exception a RuntimeError will be
raised.

601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
Static member method
--------------------

If the Rectangle class has a static member:

.. sourcecode:: c++

    namespace shapes {
        class Rectangle {
        ...
        public:
            static void do_something();

        };
    }

Robert Bradshaw's avatar
Robert Bradshaw committed
617
you can declare it using the Python @staticmethod decorator, i.e.::
618

Robert Bradshaw's avatar
Robert Bradshaw committed
619
    cdef extern from "Rectangle.h" namespace "shapes":
620 621 622 623
        cdef cppclass Rectangle:
            ...
            @staticmethod
            void do_something()
624

Robert Bradshaw's avatar
Robert Bradshaw committed
625

626 627 628 629 630 631 632 633 634
Declaring/Using References
---------------------------

Cython supports declaring lvalue references using the standard ``Type&`` syntax.
Note, however, that it is unnecessary to declare the arguments of extern
functions as references (const or otherwise) as it has no impact on the
caller's syntax.


635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
``auto`` Keyword
----------------

Though Cython does not have an ``auto`` keyword, Cython local variables
not explicitly typed with ``cdef`` are deduced from the types of the right hand
side of *all* their assignments (see the ``infer_types``
:ref:`compiler directive <compiler-directives>`).  This is particularly handy
when dealing with functions that return complicated, nested, templated types,
e.g.::

    cdef vector[int] v = ...
    it = v.begin()

(Though of course the ``for .. in`` syntax is prefered for objects supporting
the iteration protocol.)

651 652 653
RTTI and typeid()
=================

654
Cython has support for the ``typeid(...)`` operator.
655 656 657 658 659 660 661 662

    from cython.operator cimport typeid

The ``typeid(...)`` operator returns an object of the type ``const type_info &``.

If you want to store a type_info value in a C variable, you will need to store it
as a pointer rather than a reference:

663
    from libcpp.typeinfo cimport type_info
664 665 666 667 668 669 670 671
    cdef const type_info* info = &typeid(MyClass)

If an invalid type is passed to ``typeid``, it will throw an ``std::bad_typeid``
exception which is converted into a ``TypeError`` exception in Python.

An additional C++11-only RTTI-related class, ``std::type_index``, is available
in ``libcpp.typeindex``.

672

673 674
Caveats and Limitations
========================
Robert Bradshaw's avatar
Robert Bradshaw committed
675

676 677
Access to C-only functions
---------------------------
Robert Bradshaw's avatar
Robert Bradshaw committed
678

679
Whenever generating C++ code, Cython generates declarations of and calls
Stefan Behnel's avatar
Stefan Behnel committed
680 681
to functions assuming these functions are C++ (ie, not declared as ``extern "C"
{...}``. This is ok if the C functions have C++ entry points, but if they're C
682 683 684
only, you will hit a roadblock. If you have a C++ Cython module needing
to make calls to pure-C functions, you will need to write a small C++ shim
module which:
Robert Bradshaw's avatar
Robert Bradshaw committed
685

686 687
* includes the needed C headers in an extern "C" block
* contains minimal forwarding functions in C++, each of which calls the
688
  respective pure-C function
Robert Bradshaw's avatar
Robert Bradshaw committed
689

690 691 692
C++ left-values
----------------

693 694 695
C++ allows functions returning a reference to be left-values.  This is currently
not supported in Cython. ``cython.operator.dereference(foo)`` is also not
considered a left-value.