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: "", importc: "printf", varargs.} Note that this pragma is somewhat of a misnomer: Other backends do provide the same feature under the same name. Also, if one is interfacing with C++ the `ImportCpp pragma `_ and interfacing with Objective-C the `ImportObjC pragma `_ can be used. The string literal passed to ``importc`` can be a format string: .. code-block:: Nim proc p(s: cstring) {.importc: "prefix$1".} In the example the external name of ``p`` is set to ``prefixp``. Only ``$1`` is available and a literal dollar sign must be written as ``$$``. 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 do provide the same feature under the same name. The string literal passed to ``exportc`` can be a format string: .. code-block:: Nim proc p(s: string) {.exportc: "prefix$1".} = echo s In the example the external name of ``p`` is set to ``prefixp``. Only ``$1`` is available and a literal dollar sign must be written as ``$$``. 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``. Only ``$1`` is available and a literal dollar sign must be written as ``$$``. 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 Vector {.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 to implement customized flexibly sized arrays. Additionally an unchecked array is translated into a C array of undetermined size: .. code-block:: nim type ArrayPart{.unchecked.} = array[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 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 overridden 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. This pragma only has an effect for the code generation on the Windows target, so when this pragma is forgotten and the dynamic library is only tested on Mac and/or Linux, there won't be an error. On Windows this pragma adds ``__declspec(dllexport)`` to the function declaration.