mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 18:02:05 +00:00
230 lines
7.4 KiB
Plaintext
230 lines
7.4 KiB
Plaintext
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 do provide
|
|
the same feature under the same name. Also, if one is interfacing with C++
|
|
the `ImportCpp pragma <manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
|
|
interfacing with Objective-C the `ImportObjC pragma
|
|
<manual.html#implementation-specific-pragmas-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 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. 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.
|
|
|