backends.rst 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. ================================
  2. Nim Backend Integration
  3. ================================
  4. :Author: Puppet Master
  5. :Version: |nimversion|
  6. .. default-role:: code
  7. .. include:: rstcommon.rst
  8. .. no syntax highlighting here by default:
  9. .. contents::
  10. "Heresy grows from idleness." -- Unknown.
  11. Introduction
  12. ============
  13. The `Nim Compiler User Guide <nimc.html>`_ documents the typical
  14. compiler invocation, using the `compile`:option:
  15. or `c`:option: command to transform a
  16. ``.nim`` file into one or more ``.c`` files which are then compiled with the
  17. platform's C compiler into a static binary. However, there are other commands
  18. to compile to C++, Objective-C, or JavaScript. This document tries to
  19. concentrate in a single place all the backend and interfacing options.
  20. The Nim compiler supports mainly two backend families: the C, C++ and
  21. Objective-C targets and the JavaScript target. `The C like targets
  22. <#backends-the-c-like-targets>`_ creates source files that can be compiled
  23. into a library or a final executable. `The JavaScript target
  24. <#backends-the-javascript-target>`_ can generate a ``.js`` file which you
  25. reference from an HTML file or create a `standalone Node.js program
  26. <http://nodejs.org>`_.
  27. On top of generating libraries or standalone applications, Nim offers
  28. bidirectional interfacing with the backend targets through generic and
  29. specific pragmas.
  30. Backends
  31. ========
  32. The C like targets
  33. ------------------
  34. The commands to compile to either C, C++ or Objective-C are:
  35. //compileToC, cc compile project with C code generator
  36. //compileToCpp, cpp compile project to C++ code
  37. //compileToOC, objc compile project to Objective C code
  38. The most significant difference between these commands is that if you look
  39. into the ``nimcache`` directory you will find ``.c``, ``.cpp`` or ``.m``
  40. files, other than that all of them will produce a native binary for your
  41. project. This allows you to take the generated code and place it directly
  42. into a project using any of these languages. Here are some typical command-
  43. line invocations:
  44. .. code:: cmd
  45. nim c hallo.nim
  46. nim cpp hallo.nim
  47. nim objc hallo.nim
  48. The compiler commands select the target backend, but if needed you can
  49. `specify additional switches for cross-compilation
  50. <nimc.html#crossminuscompilation>`_ to select the target CPU, operative system
  51. or compiler/linker commands.
  52. The JavaScript target
  53. ---------------------
  54. Nim can also generate `JavaScript`:idx: code through the `js`:option: command.
  55. Nim targets JavaScript 1.5 which is supported by any widely used browser.
  56. Since JavaScript does not have a portable means to include another module,
  57. Nim just generates a long ``.js`` file.
  58. Features or modules that the JavaScript platform does not support are not
  59. available. This includes:
  60. * manual memory management (`alloc`, etc.)
  61. * casting and other unsafe operations (`cast` operator, `zeroMem`, etc.)
  62. * file management
  63. * OS-specific operations
  64. * threading, coroutines
  65. * some modules of the standard library
  66. * proper 64-bit integer arithmetic
  67. To compensate, the standard library has modules `catered to the JS backend
  68. <lib.html#pure-libraries-modules-for-js-backend>`_
  69. and more support will come in the future (for instance, Node.js bindings
  70. to get OS info).
  71. To compile a Nim module into a ``.js`` file use the `js`:option: command; the
  72. default is a ``.js`` file that is supposed to be referenced in an ``.html``
  73. file. However, you can also run the code with `nodejs`:idx:
  74. (`<http://nodejs.org>`_):
  75. .. code:: cmd
  76. nim js -d:nodejs -r examples/hallo.nim
  77. If you experience errors saying that `globalThis` is not defined, be
  78. sure to run a recent version of Node.js (at least 12.0).
  79. Interfacing
  80. ===========
  81. Nim offers bidirectional interfacing with the target backend. This means
  82. that you can call backend code from Nim and Nim code can be called by
  83. the backend code. Usually the direction of which calls which depends on your
  84. software architecture (is Nim your main program or is Nim providing a
  85. component?).
  86. Nim code calling the backend
  87. ----------------------------
  88. Nim code can interface with the backend through the `Foreign function
  89. interface <manual.html#foreign-function-interface>`_ mainly through the
  90. `importc pragma <manual.html#foreign-function-interface-importc-pragma>`_.
  91. The `importc` pragma is the *generic* way of making backend symbols available
  92. in Nim and is available in all the target backends (JavaScript too). The C++
  93. or Objective-C backends have their respective `ImportCpp
  94. <manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
  95. `ImportObjC <manual.html#implementation-specific-pragmas-importobjc-pragma>`_
  96. pragmas to call methods from classes.
  97. Whenever you use any of these pragmas you need to integrate native code into
  98. your final binary. In the case of JavaScript this is no problem at all, the
  99. same HTML file which hosts the generated JavaScript will likely provide other
  100. JavaScript functions which you are importing with `importc`.
  101. However, for the C like targets you need to link external code either
  102. statically or dynamically. The preferred way of integrating native code is to
  103. use dynamic linking because it allows you to compile Nim programs without
  104. the need for having the related development libraries installed. This is done
  105. through the `dynlib pragma for import
  106. <manual.html#foreign-function-interface-dynlib-pragma-for-import>`_, though
  107. more specific control can be gained using the `dynlib module <dynlib.html>`_.
  108. The `dynlibOverride <nimc.html#dynliboverride>`_ command line switch allows
  109. to avoid dynamic linking if you need to statically link something instead.
  110. Nim wrappers designed to statically link source files can use the `compile
  111. pragma <manual.html#implementation-specific-pragmas-compile-pragma>`_ if
  112. there are few sources or providing them along the Nim code is easier than using
  113. a system library. Libraries installed on the host system can be linked in with
  114. the `PassL pragma <manual.html#implementation-specific-pragmas-passl-pragma>`_.
  115. To wrap native code, take a look at the `c2nim tool <https://github.com/nim-lang/c2nim/blob/master/doc/c2nim.rst>`_ which helps
  116. with the process of scanning and transforming header files into a Nim
  117. interface.
  118. C invocation example
  119. ~~~~~~~~~~~~~~~~~~~~
  120. Create a ``logic.c`` file with the following content:
  121. .. code-block:: c
  122. int addTwoIntegers(int a, int b)
  123. {
  124. return a + b;
  125. }
  126. Create a ``calculator.nim`` file with the following content:
  127. .. code-block:: nim
  128. {.compile: "logic.c".}
  129. proc addTwoIntegers(a, b: cint): cint {.importc.}
  130. when isMainModule:
  131. echo addTwoIntegers(3, 7)
  132. With these two files in place, you can run `nim c -r calculator.nim`:cmd: and
  133. the Nim compiler will compile the ``logic.c`` file in addition to
  134. ``calculator.nim`` and link both into an executable, which outputs `10` when
  135. run. Another way to link the C file statically and get the same effect would
  136. be to remove the line with the `compile` pragma and run the following
  137. typical Unix commands:
  138. .. code:: cmd
  139. gcc -c logic.c
  140. ar rvs mylib.a logic.o
  141. nim c --passL:mylib.a -r calculator.nim
  142. Just like in this example we pass the path to the ``mylib.a`` library (and we
  143. could as well pass ``logic.o``) we could be passing switches to link any other
  144. static C library.
  145. JavaScript invocation example
  146. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  147. Create a ``host.html`` file with the following content:
  148. .. code-block::
  149. <html><body>
  150. <script type="text/javascript">
  151. function addTwoIntegers(a, b)
  152. {
  153. return a + b;
  154. }
  155. </script>
  156. <script type="text/javascript" src="calculator.js"></script>
  157. </body></html>
  158. Create a ``calculator.nim`` file with the following content (or reuse the one
  159. from the previous section):
  160. .. code-block:: nim
  161. proc addTwoIntegers(a, b: int): int {.importc.}
  162. when isMainModule:
  163. echo addTwoIntegers(3, 7)
  164. Compile the Nim code to JavaScript with `nim js -o:calculator.js
  165. calculator.nim`:cmd: and open ``host.html`` in a browser. If the browser supports
  166. javascript, you should see the value `10` in the browser's console. Use the
  167. `dom module <dom.html>`_ for specific DOM querying and modification procs
  168. or take a look at `karax <https://github.com/pragmagic/karax>`_ for how to
  169. develop browser-based applications.
  170. Backend code calling Nim
  171. ------------------------
  172. Backend code can interface with Nim code exposed through the `exportc
  173. pragma <manual.html#foreign-function-interface-exportc-pragma>`_. The
  174. `exportc` pragma is the *generic* way of making Nim symbols available to
  175. the backends. By default, the Nim compiler will mangle all the Nim symbols to
  176. avoid any name collision, so the most significant thing the `exportc` pragma
  177. does is maintain the Nim symbol name, or if specified, use an alternative
  178. symbol for the backend in case the symbol rules don't match.
  179. The JavaScript target doesn't have any further interfacing considerations
  180. since it also has garbage collection, but the C targets require you to
  181. initialize Nim's internals, which is done calling a `NimMain` function.
  182. Also, C code requires you to specify a forward declaration for functions or
  183. the compiler will assume certain types for the return value and parameters
  184. which will likely make your program crash at runtime.
  185. The Nim compiler can generate a C interface header through the `--header`:option:
  186. command-line switch. The generated header will contain all the exported
  187. symbols and the `NimMain` proc which you need to call before any other
  188. Nim code.
  189. Nim invocation example from C
  190. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  191. Create a ``fib.nim`` file with the following content:
  192. .. code-block:: nim
  193. proc fib(a: cint): cint {.exportc.} =
  194. if a <= 2:
  195. result = 1
  196. else:
  197. result = fib(a - 1) + fib(a - 2)
  198. Create a ``maths.c`` file with the following content:
  199. .. code-block:: c
  200. #include "fib.h"
  201. #include <stdio.h>
  202. int main(void)
  203. {
  204. NimMain();
  205. for (int f = 0; f < 10; f++)
  206. printf("Fib of %d is %d\n", f, fib(f));
  207. return 0;
  208. }
  209. Now you can run the following Unix like commands to first generate C sources
  210. from the Nim code, then link them into a static binary along your main C
  211. program:
  212. .. code:: cmd
  213. nim c --noMain --noLinking --header:fib.h fib.nim
  214. gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
  215. The first command runs the Nim compiler with three special options to avoid
  216. generating a `main()`:c: function in the generated files, avoid linking the
  217. object files into a final binary, and explicitly generate a header file for C
  218. integration. All the generated files are placed into the ``nimcache``
  219. directory. That's why the next command compiles the ``maths.c`` source plus
  220. all the ``.c`` files from ``nimcache``. In addition to this path, you also
  221. have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
  222. Instead of depending on the generation of the individual ``.c`` files you can
  223. also ask the Nim compiler to generate a statically linked library:
  224. .. code:: cmd
  225. nim c --app:staticLib --noMain --header fib.nim
  226. gcc -o m -Inimcache -Ipath/to/nim/lib libfib.nim.a maths.c
  227. The Nim compiler will handle linking the source files generated in the
  228. ``nimcache`` directory into the ``libfib.nim.a`` static library, which you can
  229. then link into your C program. Note that these commands are generic and will
  230. vary for each system. For instance, on Linux systems you will likely need to
  231. use `-ldl`:option: too to link in required dlopen functionality.
  232. Nim invocation example from JavaScript
  233. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  234. Create a ``mhost.html`` file with the following content:
  235. .. code-block::
  236. <html><body>
  237. <script type="text/javascript" src="fib.js"></script>
  238. <script type="text/javascript">
  239. alert("Fib for 9 is " + fib(9));
  240. </script>
  241. </body></html>
  242. Create a ``fib.nim`` file with the following content (or reuse the one
  243. from the previous section):
  244. .. code-block:: nim
  245. proc fib(a: cint): cint {.exportc.} =
  246. if a <= 2:
  247. result = 1
  248. else:
  249. result = fib(a - 1) + fib(a - 2)
  250. Compile the Nim code to JavaScript with `nim js -o:fib.js fib.nim`:cmd: and
  251. open ``mhost.html`` in a browser. If the browser supports javascript, you
  252. should see an alert box displaying the text ``Fib for 9 is 34``. As mentioned
  253. earlier, JavaScript doesn't require an initialization call to `NimMain` or
  254. a similar function and you can call the exported Nim proc directly.
  255. Nimcache naming logic
  256. ---------------------
  257. The `nimcache`:idx: directory is generated during compilation and will hold
  258. either temporary or final files depending on your backend target. The default
  259. name for the directory depends on the used backend and on your OS but you can
  260. use the `--nimcache`:option: `compiler switch
  261. <nimc.html#compiler-usage-commandminusline-switches>`_ to change it.
  262. Memory management
  263. =================
  264. In the previous sections, the `NimMain()` function reared its head. Since
  265. JavaScript already provides automatic memory management, you can freely pass
  266. objects between the two languages without problems. In C and derivate languages
  267. you need to be careful about what you do and how you share memory. The
  268. previous examples only dealt with simple scalar values, but passing a Nim
  269. string to C, or reading back a C string in Nim already requires you to be
  270. aware of who controls what to avoid crashing.
  271. Strings and C strings
  272. ---------------------
  273. The manual mentions that `Nim strings are implicitly convertible to
  274. cstrings <manual.html#types-cstring-type>`_ which makes interaction usually
  275. painless. Most C functions accepting a Nim string converted to a
  276. `cstring` will likely not need to keep this string around and by the time
  277. they return the string won't be needed anymore. However, for the rare cases
  278. where a Nim string has to be preserved and made available to the C backend
  279. as a `cstring`, you will need to manually prevent the string data
  280. from being freed with `GC_ref <system.html#GC_ref,string>`_ and `GC_unref
  281. <system.html#GC_unref,string>`_.
  282. A similar thing happens with C code invoking Nim code which returns a
  283. `cstring`. Consider the following proc:
  284. .. code-block:: nim
  285. proc gimme(): cstring {.exportc.} =
  286. result = "Hey there C code! " & $rand(100)
  287. Since Nim's garbage collector is not aware of the C code, once the
  288. `gimme` proc has finished it can reclaim the memory of the `cstring`.
  289. However, from a practical standpoint, the C code invoking the `gimme`
  290. function directly will be able to use it since Nim's garbage collector has
  291. not had a chance to run *yet*. This gives you enough time to make a copy for
  292. the C side of the program, as calling any further Nim procs *might* trigger
  293. garbage collection making the previously returned string garbage. Or maybe you
  294. are `yourself triggering the collection <gc.html>`_.
  295. Custom data types
  296. -----------------
  297. Just like strings, custom data types that are to be shared between Nim and
  298. the backend will need careful consideration of who controls who. If you want
  299. to hand a Nim reference to C code, you will need to use `GC_ref
  300. <system.html#GC_ref,ref.T>`_ to mark the reference as used, so it does not get
  301. freed. And for the C backend you will need to expose the `GC_unref
  302. <system.html#GC_unref,ref.T>`_ proc to clean up this memory when it is not
  303. required anymore.
  304. Again, if you are wrapping a library which *mallocs* and *frees* data
  305. structures, you need to expose the appropriate *free* function to Nim so
  306. you can clean it up. And of course, once cleaned you should avoid accessing it
  307. from Nim (or C for that matter). Typically C data structures have their own
  308. `malloc_structure`:c: and `free_structure`:c: specific functions, so wrapping
  309. these for the Nim side should be enough.
  310. Thread coordination
  311. -------------------
  312. When the `NimMain()` function is called Nim initializes the garbage
  313. collector to the current thread, which is usually the main thread of your
  314. application. If your C code later spawns a different thread and calls Nim
  315. code, the garbage collector will fail to work properly and you will crash.
  316. As long as you don't use the threadvar emulation Nim uses native thread
  317. variables, of which you get a fresh version whenever you create a thread. You
  318. can then attach a GC to this thread via
  319. .. code-block:: nim
  320. system.setupForeignThreadGc()
  321. It is **not** safe to disable the garbage collector and enable it after the
  322. call from your background thread even if the code you are calling is short
  323. lived.
  324. Before the thread exits, you should tear down the thread's GC to prevent memory
  325. leaks by calling
  326. .. code-block:: nim
  327. system.tearDownForeignThreadGc()