documented new C++ support
This commit is contained in:
parent
85ae439bb8
commit
dbe71c715e
8 changed files with 185 additions and 29 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
190
doc/nimc.txt
190
doc/nimc.txt
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -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!
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue