documented new C++ support

This commit is contained in:
Araq 2015-01-28 10:52:13 +01:00
commit dbe71c715e
8 changed files with 185 additions and 29 deletions

View file

@ -421,7 +421,7 @@ returned by idetools returns also the pragmas for the proc.
| **Docstring**: docstring if available. | **Docstring**: docstring if available.
.. code-block:: nim .. code-block:: nim
Open(filename, fmWrite) open(filename, fmWrite)
--> col 2: system.Open --> col 2: system.Open
col 3: proc (var File, string, FileMode, int): bool col 3: proc (var File, string, FileMode, int): bool
col 7: col 7:

View file

@ -393,12 +393,18 @@ Use two backticks to produce a single verbatim backtick.
ImportCpp pragma ImportCpp pragma
---------------- ----------------
**Note**: `c2nim <c2nim.html>`_ can parse a large subset of C++ and knows
about the ``importcpp`` pragma pattern language. It is not necessary
to know all the details described here.
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the
``importcpp`` pragma can be used to import `C++`:idx: methods. The generated ``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols
code then uses the C++ method calling syntax: ``obj->method(arg)``. In in general. The generated code then uses the C++ method calling
addition with the ``header`` and ``emit`` pragmas this allows *sloppy* syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit``
interfacing with libraries written in C++: pragmas this allows *sloppy* interfacing with libraries written in C++:
.. code-block:: Nim .. code-block:: Nim
# Horrible example of how to interface with a C++ engine ... ;-) # Horrible example of how to interface with a C++ engine ... ;-)
@ -418,18 +424,168 @@ interfacing with libraries written in C++:
irr = "<irrlicht/irrlicht.h>" irr = "<irrlicht/irrlicht.h>"
type type
IrrlichtDeviceObj {.final, header: irr, importc: "IrrlichtDevice".} = object IrrlichtDeviceObj {.final, header: irr,
importcpp: "IrrlichtDevice".} = object
IrrlichtDevice = ptr IrrlichtDeviceObj IrrlichtDevice = ptr IrrlichtDeviceObj
proc createDevice(): PIrrlichtDevice {. proc createDevice(): IrrlichtDevice {.
header: irr, importc: "createDevice".} header: irr, importcpp: "createDevice(@)".}
proc run(device: PIrrlichtDevice): bool {. proc run(device: IrrlichtDevice): bool {.
header: irr, importcpp: "run".} header: irr, importcpp: "#.run(@)".}
The compiler needs to be told to generate C++ (command ``cpp``) for The compiler needs to be told to generate C++ (command ``cpp``) for
this to work. The conditional symbol ``cpp`` is defined when the compiler this to work. The conditional symbol ``cpp`` is defined when the compiler
emits C++ code. emits C++ code.
Namespaces
~~~~~~~~~~
The *sloppy interfacing* example uses ``.emit`` to produce ``using namespace``
declarations. It is usually much better to instead refer to the imported name
via the ``namespace::identifier`` notation:
.. code-block:: nim
type
IrrlichtDeviceObj {.final, header: irr,
importcpp: "irr::IrrlichtDevice".} = object
Importcpp for enums
~~~~~~~~~~~~~~~~~~~
When ``importcpp`` is applied to an enum type the numerical enum values are
annotated with the C++ enum type, like in this example: ``((TheCppEnum)(3))``.
(This turned out to be the simplest way to implement it.)
Importcpp for procs
~~~~~~~~~~~~~~~~~~~
Note that the ``importcpp`` variant for procs uses a somewhat cryptic pattern
language for maximum flexibility:
- A hash ``#`` symbol is replaced by the first or next argument.
- A dot following the hash ``#.`` indicates that the call should use C++'s dot
or arrow notation.
- An at symbol ``@`` is replaced by the remaining arguments, separated by
commas.
For example:
.. code-block:: nim
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".}
var x: ptr CppObj
cppMethod(x[], 1, 2, 3)
Produces:
.. code-block:: C
x->CppMethod(1, 2, 3)
As a special rule to keep backwards compatibility with older versions of the
``importcpp`` pragma, if there is no special pattern
character (any of ``# ' @``) at all, C++'s
dot or arrow notation is assumed, so the above example can also be written as:
.. code-block:: nim
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".}
Note that the pattern language naturally also covers C++'s operator overloading
capabilities:
.. code-block:: nim
proc vectorAddition(a, b: Vec3): Vec3 {.importcpp: "# + #".}
proc dictLookup(a: Dict, k: Key): Value {.importcpp: "#[#]".}
- An apostrophe ``'`` followed by an integer ``i`` in the range 0..9
is replaced by the i'th parameter *type*. The 0th position is the result
type. This can be used to pass types to C++ function templates. Between
the ``'`` and the digit an asterisk can be used to get to the base type
of the type. (So it "takes away a star" from the type; ``T*`` becomes ``T``.)
Two stars can be used to get to the element type of the element type etc.
For example:
.. code-block:: nim
type Input {.importcpp: "System::Input".} = object
proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()".}
let x: ptr Input = getSubsystem[Input]()
Produces:
.. code-block:: C
x = SystemManager::getSubsystem<System::Input>()
- ``#@`` is a special case to support a ``cnew`` operation. It is required so
that the call expression is inlined directly, without going through a
temporary location. This is only required to circumvent a limitation of the
current code generator.
For example C++'s ``new`` operator can be "imported" like this:
.. code-block:: nim
proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.}
# constructor of 'Foo':
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".}
let x = cnew constructFoo(3, 4)
Produces:
.. code-block:: C
x = new Foo(3, 4)
However, depending on the use case ``new Foo`` can also be wrapped like this
instead:
.. code-block:: nim
proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".}
let x = newFoo(3, 4)
Wrapping destructors
~~~~~~~~~~~~~~~~~~~~
Since Nim generates C++ directly, any destructor is called implicitly by the
C++ compiler at the scope exits. This means that often one can get away with
not wrapping the destructor at all! However when it needs to be invoked
explicitly, it needs to be wrapped. But the pattern language already provides
everything that is required for that:
.. code-block:: nim
proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".}
Importcpp for objects
~~~~~~~~~~~~~~~~~~~~~
Generic ``importcpp``'ed objects are mapped to C++ templates. This means that
you can import C++'s templates rather easily without the need for a pattern
language for object types:
.. code-block:: nim
type
StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object
proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {.
importcpp: "#[#] = #".}
var x: StdMap[cint, cdouble]
x[6] = 91.4
Produces:
.. code-block:: C
std::map<int, double> x;
x[6] = 91.4;
ImportObjC pragma ImportObjC pragma
----------------- -----------------
@ -607,7 +763,7 @@ line is an incomplete statement to be continued these rules are used:
Nim for embedded systems Nim for embedded systems
======================== ========================
The standard library can be avoided to a point where C code generation The standard library can be avoided to a point where C code generation
for 16bit micro controllers is feasible. Use the `standalone`:idx: target for 16bit micro controllers is feasible. Use the `standalone`:idx: target
(``--os:standalone``) for a bare bones standard library that lacks any (``--os:standalone``) for a bare bones standard library that lacks any
OS features. OS features.
@ -619,9 +775,9 @@ For example, to generate code for an `AVR`:idx: processor use this command::
nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim
For the ``standalone`` target you need to provide For the ``standalone`` target one needs to provide
a file ``panicoverride.nim``. a file ``panicoverride.nim``.
See ``tests/manyloc/standalone/panicoverride.nim`` for an example See ``tests/manyloc/standalone/panicoverride.nim`` for an example
implementation. implementation.

View file

@ -12,7 +12,7 @@
## by Adam Langley. ## by Adam Langley.
type type
NodeObj[T] = object {.pure, final, acyclic.} NodeObj[T] = object {.acyclic.}
byte: int ## byte index of the difference byte: int ## byte index of the difference
otherbits: char otherbits: char
case isLeaf: bool case isLeaf: bool
@ -23,11 +23,10 @@ type
val: T val: T
Node[T] = ref NodeObj[T] Node[T] = ref NodeObj[T]
CritBitTree*[T] = object {. CritBitTree*[T] = object ## The crit bit tree can either be used
pure, final.} ## The crit bit tree can either be used ## as a mapping from strings to
## as a mapping from strings to ## some type ``T`` or as a set of
## some type ``T`` or as a set of ## strings if ``T`` is void.
## strings if ``T`` is void.
root: Node[T] root: Node[T]
count: int count: int

View file

@ -8,7 +8,7 @@
# #
## The ``intsets`` module implements an efficient int set implemented as a ## The ``intsets`` module implements an efficient int set implemented as a
## sparse bit set. ## `sparse bit set`:idx:.
## **Note**: Since Nim currently does not allow the assignment operator to ## **Note**: Since Nim currently does not allow the assignment operator to
## be overloaded, ``=`` for int sets performs some rather meaningless shallow ## be overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy; use ``assign`` to get a deep copy. ## copy; use ``assign`` to get a deep copy.

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Implementation of a queue. The underlying implementation uses a ``seq``. ## Implementation of a `queue`:idx:. The underlying implementation uses a ``seq``.
## Note: For inter thread communication use ## Note: For inter thread communication use
## a `TChannel <channels.html>`_ instead. ## a `TChannel <channels.html>`_ instead.

View file

@ -7,7 +7,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## The ``sets`` module implements an efficient hash set and ordered hash set. ## The ``sets`` module implements an efficient `hash set`:idx: and
## ordered hash set.
## ##
## Hash sets are different from the `built in set type ## Hash sets are different from the `built in set type
## <manual.html#set-type>`_. Sets allow you to store any value that can be ## <manual.html#set-type>`_. Sets allow you to store any value that can be

View file

@ -7,7 +7,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## The ``tables`` module implements variants of an efficient hash table that is ## The ``tables`` module implements variants of an efficient `hash table`:idx:
## (also often named `dictionary`:idx: in other programming languages) that is
## a mapping from keys to values. ``Table`` is the usual hash table, ## a mapping from keys to values. ``Table`` is the usual hash table,
## ``OrderedTable`` is like ``Table`` but remembers insertion order ## ``OrderedTable`` is like ``Table`` but remembers insertion order
## and ``CountTable`` is a mapping from a key to its number of occurances. ## and ``CountTable`` is a mapping from a key to its number of occurances.

View file

@ -1,7 +1,6 @@
version 0.10 version 0.10
============ ============
- document the improved c++ support
- improve the docs for inheritance - improve the docs for inheritance
- The bitwise 'not' operator will be renamed to 'bnot' to - The bitwise 'not' operator will be renamed to 'bnot' to
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs! prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!