1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
Foreign function interface
==========================
Nim's `FFI`:idx: (foreign function interface) is extensive and only the
parts that scale to other future backends (like the LLVM/JavaScript backends)
are documented here.
Importc pragma
--------------
The ``importc`` pragma provides a means to import a proc or a variable
from C. The optional argument is a string containing the C identifier. If
the argument is missing, the C name is the Nim identifier *exactly as
spelled*:
.. code-block::
proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
Note that this pragma is somewhat of a misnomer: Other backends will provide
the same feature under the same name. Also, if one is interfacing with C++
the `ImportCpp pragma <nimc.html#importcpp-pragma>`_ and
interfacing with Objective-C the `ImportObjC pragma
<nimc.html#importobjc-pragma>`_ can be used.
Exportc pragma
--------------
The ``exportc`` pragma provides a means to export a type, a variable, or a
procedure to C. Enums and constants can't be exported. The optional argument
is a string containing the C identifier. If the argument is missing, the C
name is the Nim identifier *exactly as spelled*:
.. code-block:: Nim
proc callme(formatstr: cstring) {.exportc: "callMe", varargs.}
Note that this pragma is somewhat of a misnomer: Other backends will provide
the same feature under the same name.
Extern pragma
-------------
Like ``exportc`` or ``importc``, the ``extern`` pragma affects name
mangling. The string literal passed to ``extern`` can be a format string:
.. code-block:: Nim
proc p(s: string) {.extern: "prefix$1".} =
echo s
In the example the external name of ``p`` is set to ``prefixp``.
Bycopy pragma
-------------
The ``bycopy`` pragma can be applied to an object or tuple type and
instructs the compiler to pass the type by value to procs:
.. code-block:: nim
type
TVector {.bycopy, pure.} = object
x, y, z: float
Byref pragma
------------
The ``byref`` pragma can be applied to an object or tuple type and instructs
the compiler to pass the type by reference (hidden pointer) to procs.
Varargs pragma
--------------
The ``varargs`` pragma can be applied to procedures only (and procedure
types). It tells Nim that the proc can take a variable number of parameters
after the last specified parameter. Nim string values will be converted to C
strings automatically:
.. code-block:: Nim
proc printf(formatstr: cstring) {.nodecl, varargs.}
printf("hallo %s", "world") # "world" will be passed as C string
Union pragma
------------
The ``union`` pragma can be applied to any ``object`` type. It means all
of the object's fields are overlaid in memory. This produces a ``union``
instead of a ``struct`` in the generated C/C++ code. The object declaration
then must not use inheritance or any GC'ed memory but this is currently not
checked.
**Future directions**: GC'ed memory should be allowed in unions and the GC
should scan unions conservatively.
Packed pragma
-------------
The ``packed`` pragma can be applied to any ``object`` type. It ensures
that the fields of an object are packed back-to-back in memory. It is useful
to store packets or messages from/to network or hardware drivers, and for
interoperability with C. Combining packed pragma with inheritance is not
defined, and it should not be used with GC'ed memory (ref's).
**Future directions**: Using GC'ed memory in packed pragma will result in
compile-time error. Usage with inheritance should be defined and documented.
Unchecked pragma
----------------
The ``unchecked`` pragma can be used to mark a named array as ``unchecked``
meaning its bounds are not checked. This is often useful when one wishes to
implement his own flexibly sized arrays. Additionally an unchecked array is
translated into a C array of undetermined size:
.. code-block:: nim
type
ArrayPart{.unchecked.} = array[0..0, int]
MySeq = object
len, cap: int
data: ArrayPart
Produces roughly this C code:
.. code-block:: C
typedef struct {
NI len;
NI cap;
NI data[];
} MySeq;
The bounds checking done at compile time is not disabled for now, so to access
``s.data[C]`` (where ``C`` is a constant) the array's index needs needs to
include ``C``.
The base type of the unchecked array may not contain any GC'ed memory but this
is currently not checked.
**Future directions**: GC'ed memory should be allowed in unchecked arrays and
there should be an explicit annotation of how the GC is to determine the
runtime size of the array.
Dynlib pragma for import
------------------------
With the ``dynlib`` pragma a procedure or a variable can be imported from
a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX).
The non-optional argument has to be the name of the dynamic library:
.. code-block:: Nim
proc gtk_image_new(): PGtkWidget
{.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
In general, importing a dynamic library does not require any special linker
options or linking with import libraries. This also implies that no *devel*
packages need to be installed.
The ``dynlib`` import mechanism supports a versioning scheme:
.. code-block:: nim
proc Tcl_Eval(interp: pTcl_Interp, script: cstring): int {.cdecl,
importc, dynlib: "libtcl(|8.5|8.4|8.3).so.(1|0)".}
At runtime the dynamic library is searched for (in this order)::
libtcl.so.1
libtcl.so.0
libtcl8.5.so.1
libtcl8.5.so.0
libtcl8.4.so.1
libtcl8.4.so.0
libtcl8.3.so.1
libtcl8.3.so.0
The ``dynlib`` pragma supports not only constant strings as argument but also
string expressions in general:
.. code-block:: nim
import os
proc getDllName: string =
result = "mylib.dll"
if existsFile(result): return
result = "mylib2.dll"
if existsFile(result): return
quit("could not load dynamic library")
proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().}
**Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant
strings, because they are precompiled.
**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime
because of order of initialization problems.
**Note**: A ``dynlib`` import can be overriden with
the ``--dynlibOverride:name`` command line option. The Compiler User Guide
contains further information.
Dynlib pragma for export
------------------------
With the ``dynlib`` pragma a procedure can also be exported to
a dynamic library. The pragma then has no argument and has to be used in
conjunction with the ``exportc`` pragma:
.. code-block:: Nim
proc exportme(): int {.cdecl, exportc, dynlib.}
This is only useful if the program is compiled as a dynamic library via the
``--app:lib`` command line option.
|