summary refs log tree commit diff stats
path: root/doc/manual/ffi.txt
blob: 0ad4ebba938fe0bed9804a5e1c30904c8899f4c6 (plain) (blame)
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.