documented new C++ support

This commit is contained in:
Araq
2015-01-28 10:52:13 +01:00
parent 85ae439bb8
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.
.. code-block:: nim
Open(filename, fmWrite)
open(filename, fmWrite)
--> col 2: system.Open
col 3: proc (var File, string, FileMode, int): bool
col 7:

View File

@@ -393,12 +393,18 @@ Use two backticks to produce a single verbatim backtick.
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
``importcpp`` pragma can be used to import `C++`:idx: methods. The generated
code then uses the C++ method calling syntax: ``obj->method(arg)``. In
addition with the ``header`` and ``emit`` pragmas this allows *sloppy*
interfacing with libraries written in C++:
``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols
in general. The generated code then uses the C++ method calling
syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit``
pragmas this allows *sloppy* interfacing with libraries written in C++:
.. code-block:: Nim
# Horrible example of how to interface with a C++ engine ... ;-)
@@ -418,18 +424,168 @@ interfacing with libraries written in C++:
irr = "<irrlicht/irrlicht.h>"
type
IrrlichtDeviceObj {.final, header: irr, importc: "IrrlichtDevice".} = object
IrrlichtDeviceObj {.final, header: irr,
importcpp: "IrrlichtDevice".} = object
IrrlichtDevice = ptr IrrlichtDeviceObj
proc createDevice(): PIrrlichtDevice {.
header: irr, importc: "createDevice".}
proc run(device: PIrrlichtDevice): bool {.
header: irr, importcpp: "run".}
proc createDevice(): IrrlichtDevice {.
header: irr, importcpp: "createDevice(@)".}
proc run(device: IrrlichtDevice): bool {.
header: irr, importcpp: "#.run(@)".}
The compiler needs to be told to generate C++ (command ``cpp``) for
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
-----------------
@@ -607,7 +763,7 @@ line is an incomplete statement to be continued these rules are used:
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
(``--os:standalone``) for a bare bones standard library that lacks any
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
For the ``standalone`` target you need to provide
a file ``panicoverride.nim``.
See ``tests/manyloc/standalone/panicoverride.nim`` for an example
For the ``standalone`` target one needs to provide
a file ``panicoverride.nim``.
See ``tests/manyloc/standalone/panicoverride.nim`` for an example
implementation.

View File

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

View File

@@ -8,7 +8,7 @@
#
## 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
## be overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy; use ``assign`` to get a deep copy.

View File

@@ -7,7 +7,7 @@
# 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
## a `TChannel <channels.html>`_ instead.

View File

@@ -7,7 +7,8 @@
# 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
## <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.
#
## 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,
## ``OrderedTable`` is like ``Table`` but remembers insertion order
## and ``CountTable`` is a mapping from a key to its number of occurances.

View File

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