koffi 2.1.0-beta.2 → 2.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/ChangeLog.md +2 -2
  2. package/build/qemu/2.1.0-beta.3/koffi_darwin_arm64.tar.gz +0 -0
  3. package/build/qemu/2.1.0-beta.3/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/2.1.0-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/2.1.0-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/2.1.0-beta.3/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/2.1.0-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/build/qemu/2.1.0-beta.3/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/2.1.0-beta.3/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/2.1.0-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/build/qemu/2.1.0-beta.3/koffi_linux_x64.tar.gz +0 -0
  12. package/build/qemu/2.1.0-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/build/qemu/2.1.0-beta.3/koffi_openbsd_x64.tar.gz +0 -0
  14. package/build/qemu/2.1.0-beta.3/koffi_win32_arm64.tar.gz +0 -0
  15. package/build/qemu/2.1.0-beta.3/koffi_win32_ia32.tar.gz +0 -0
  16. package/build/qemu/2.1.0-beta.3/koffi_win32_x64.tar.gz +0 -0
  17. package/doc/Makefile +1 -1
  18. package/doc/conf.py +5 -0
  19. package/doc/dist/doctrees/changes.doctree +0 -0
  20. package/doc/dist/doctrees/environment.pickle +0 -0
  21. package/doc/dist/doctrees/functions.doctree +0 -0
  22. package/doc/dist/doctrees/index.doctree +0 -0
  23. package/doc/dist/doctrees/types.doctree +0 -0
  24. package/doc/dist/html/.buildinfo +4 -0
  25. package/doc/dist/html/_sources/benchmarks.md.txt +137 -0
  26. package/doc/dist/html/_sources/changes.md.txt +161 -0
  27. package/doc/dist/html/_sources/contribute.md.txt +127 -0
  28. package/doc/dist/html/_sources/functions.md.txt +421 -0
  29. package/doc/dist/html/_sources/index.rst.txt +39 -0
  30. package/doc/dist/html/_sources/memory.md.txt +32 -0
  31. package/doc/dist/html/_sources/platforms.md.txt +31 -0
  32. package/doc/dist/html/_sources/start.md.txt +100 -0
  33. package/doc/dist/html/_sources/types.md.txt +541 -0
  34. package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +134 -0
  35. package/doc/dist/html/_static/basic.css +932 -0
  36. package/doc/dist/html/_static/bench_linux.png +0 -0
  37. package/doc/dist/html/_static/bench_windows.png +0 -0
  38. package/doc/dist/html/_static/custom.css +22 -0
  39. package/doc/dist/html/_static/debug.css +69 -0
  40. package/doc/dist/html/_static/doctools.js +264 -0
  41. package/doc/dist/html/_static/documentation_options.js +14 -0
  42. package/doc/dist/html/_static/file.png +0 -0
  43. package/doc/dist/html/_static/jquery-3.6.0.js +10881 -0
  44. package/doc/dist/html/_static/jquery.js +2 -0
  45. package/doc/dist/html/_static/language_data.js +199 -0
  46. package/doc/dist/html/_static/minus.png +0 -0
  47. package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
  48. package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
  49. package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
  50. package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
  51. package/doc/dist/html/_static/plus.png +0 -0
  52. package/doc/dist/html/_static/pygments.css +252 -0
  53. package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
  54. package/doc/dist/html/_static/scripts/furo.js +3 -0
  55. package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +7 -0
  56. package/doc/dist/html/_static/scripts/furo.js.map +1 -0
  57. package/doc/dist/html/_static/searchtools.js +531 -0
  58. package/doc/dist/html/_static/skeleton.css +296 -0
  59. package/doc/dist/html/_static/styles/furo-extensions.css +2 -0
  60. package/doc/dist/html/_static/styles/furo-extensions.css.map +1 -0
  61. package/doc/dist/html/_static/styles/furo.css +2 -0
  62. package/doc/dist/html/_static/styles/furo.css.map +1 -0
  63. package/doc/dist/html/_static/underscore-1.13.1.js +2042 -0
  64. package/doc/dist/html/_static/underscore.js +6 -0
  65. package/doc/dist/html/benchmarks.html +571 -0
  66. package/doc/dist/html/changes.html +686 -0
  67. package/doc/dist/html/contribute.html +403 -0
  68. package/doc/dist/html/functions.html +718 -0
  69. package/doc/dist/html/genindex.html +253 -0
  70. package/doc/dist/html/index.html +359 -0
  71. package/doc/dist/html/memory.html +346 -0
  72. package/doc/dist/html/objects.inv +0 -0
  73. package/doc/dist/html/platforms.html +371 -0
  74. package/doc/dist/html/search.html +261 -0
  75. package/doc/dist/html/searchindex.js +1 -0
  76. package/doc/dist/html/start.html +384 -0
  77. package/doc/dist/html/types.html +1061 -0
  78. package/doc/make.bat +1 -1
  79. package/doc/templates/badges.html +1 -1
  80. package/doc/types.md +2 -0
  81. package/package.json +2 -1
  82. package/src/abi_arm32.cc +142 -200
  83. package/src/abi_arm64.cc +113 -122
  84. package/src/abi_riscv64.cc +76 -92
  85. package/src/abi_x64_sysv.cc +76 -92
  86. package/src/abi_x64_win.cc +76 -92
  87. package/src/abi_x86.cc +128 -164
  88. package/test/misc.c +43 -0
  89. package/test/sync.js +81 -0
  90. package/build/qemu/2.1.0-beta.2/koffi_darwin_arm64.tar.gz +0 -0
  91. package/build/qemu/2.1.0-beta.2/koffi_darwin_x64.tar.gz +0 -0
  92. package/build/qemu/2.1.0-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  93. package/build/qemu/2.1.0-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  94. package/build/qemu/2.1.0-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  95. package/build/qemu/2.1.0-beta.2/koffi_linux_arm32hf.tar.gz +0 -0
  96. package/build/qemu/2.1.0-beta.2/koffi_linux_arm64.tar.gz +0 -0
  97. package/build/qemu/2.1.0-beta.2/koffi_linux_ia32.tar.gz +0 -0
  98. package/build/qemu/2.1.0-beta.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  99. package/build/qemu/2.1.0-beta.2/koffi_linux_x64.tar.gz +0 -0
  100. package/build/qemu/2.1.0-beta.2/koffi_openbsd_ia32.tar.gz +0 -0
  101. package/build/qemu/2.1.0-beta.2/koffi_openbsd_x64.tar.gz +0 -0
  102. package/build/qemu/2.1.0-beta.2/koffi_win32_arm64.tar.gz +0 -0
  103. package/build/qemu/2.1.0-beta.2/koffi_win32_ia32.tar.gz +0 -0
  104. package/build/qemu/2.1.0-beta.2/koffi_win32_x64.tar.gz +0 -0
@@ -0,0 +1,718 @@
1
+ <!doctype html>
2
+ <html class="no-js" lang="en">
3
+ <head><meta charset="utf-8"/>
4
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
5
+ <meta name="color-scheme" content="light dark"><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
6
+ <link rel="index" title="Index" href="genindex" /><link rel="search" title="Search" href="search" /><link rel="next" title="Memory usage" href="memory" /><link rel="prev" title="Data types" href="types" />
7
+
8
+ <meta name="generator" content="sphinx-5.0.1, furo 2022.06.04.1"/>
9
+ <title>Functions - Koffi</title>
10
+ <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
11
+ <link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=40978830699223671f4072448e654b5958f38b89" />
12
+ <link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
13
+ <link rel="stylesheet" type="text/css" href="_static/custom.css" />
14
+
15
+
16
+
17
+
18
+ <style>
19
+ body {
20
+ --color-code-background: #f8f8f8;
21
+ --color-code-foreground: black;
22
+ --color-brand-primary: #FF6600;
23
+ --color-brand-content: #FF6600;
24
+
25
+ }
26
+ @media not print {
27
+ body[data-theme="dark"] {
28
+ --color-code-background: #202020;
29
+ --color-code-foreground: #d0d0d0;
30
+ --color-brand-primary: #FF6600;
31
+ --color-brand-content: #FF6600;
32
+
33
+ }
34
+ @media (prefers-color-scheme: dark) {
35
+ body:not([data-theme="light"]) {
36
+ --color-code-background: #202020;
37
+ --color-code-foreground: #d0d0d0;
38
+ --color-brand-primary: #FF6600;
39
+ --color-brand-content: #FF6600;
40
+
41
+ }
42
+ }
43
+ }
44
+ </style></head>
45
+ <body>
46
+
47
+ <script>
48
+ document.body.dataset.theme = localStorage.getItem("theme") || "auto";
49
+ </script>
50
+
51
+
52
+ <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
53
+ <symbol id="svg-toc" viewBox="0 0 24 24">
54
+ <title>Contents</title>
55
+ <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
56
+ <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
57
+ </svg>
58
+ </symbol>
59
+ <symbol id="svg-menu" viewBox="0 0 24 24">
60
+ <title>Menu</title>
61
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
62
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
63
+ <line x1="3" y1="12" x2="21" y2="12"></line>
64
+ <line x1="3" y1="6" x2="21" y2="6"></line>
65
+ <line x1="3" y1="18" x2="21" y2="18"></line>
66
+ </svg>
67
+ </symbol>
68
+ <symbol id="svg-arrow-right" viewBox="0 0 24 24">
69
+ <title>Expand</title>
70
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
71
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
72
+ <polyline points="9 18 15 12 9 6"></polyline>
73
+ </svg>
74
+ </symbol>
75
+ <symbol id="svg-sun" viewBox="0 0 24 24">
76
+ <title>Light mode</title>
77
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
78
+ stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
79
+ <circle cx="12" cy="12" r="5"></circle>
80
+ <line x1="12" y1="1" x2="12" y2="3"></line>
81
+ <line x1="12" y1="21" x2="12" y2="23"></line>
82
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
83
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
84
+ <line x1="1" y1="12" x2="3" y2="12"></line>
85
+ <line x1="21" y1="12" x2="23" y2="12"></line>
86
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
87
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
88
+ </svg>
89
+ </symbol>
90
+ <symbol id="svg-moon" viewBox="0 0 24 24">
91
+ <title>Dark mode</title>
92
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
93
+ stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
94
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
95
+ <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
96
+ </svg>
97
+ </symbol>
98
+ <symbol id="svg-sun-half" viewBox="0 0 24 24">
99
+ <title>Auto light/dark mode</title>
100
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
101
+ stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
102
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
103
+ <circle cx="12" cy="12" r="9" />
104
+ <path d="M13 12h5" />
105
+ <path d="M13 15h4" />
106
+ <path d="M13 18h1" />
107
+ <path d="M13 9h4" />
108
+ <path d="M13 6h1" />
109
+ </svg>
110
+ </symbol>
111
+ </svg>
112
+
113
+ <input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
114
+ <input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
115
+ <label class="overlay sidebar-overlay" for="__navigation">
116
+ <div class="visually-hidden">Hide navigation sidebar</div>
117
+ </label>
118
+ <label class="overlay toc-overlay" for="__toc">
119
+ <div class="visually-hidden">Hide table of contents sidebar</div>
120
+ </label>
121
+
122
+
123
+
124
+ <div class="page">
125
+ <header class="mobile-header">
126
+ <div class="header-left">
127
+ <label class="nav-overlay-icon" for="__navigation">
128
+ <div class="visually-hidden">Toggle site navigation sidebar</div>
129
+ <i class="icon"><svg><use href="#svg-menu"></use></svg></i>
130
+ </label>
131
+ </div>
132
+ <div class="header-center">
133
+ <a href="index"><div class="brand">Koffi</div></a>
134
+ </div>
135
+ <div class="header-right">
136
+ <div class="theme-toggle-container theme-toggle-header">
137
+ <button class="theme-toggle">
138
+ <div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
139
+ <svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
140
+ <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
141
+ <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
142
+ </button>
143
+ </div>
144
+ <label class="toc-overlay-icon toc-header-icon" for="__toc">
145
+ <div class="visually-hidden">Toggle table of contents sidebar</div>
146
+ <i class="icon"><svg><use href="#svg-toc"></use></svg></i>
147
+ </label>
148
+ </div>
149
+ </header>
150
+ <aside class="sidebar-drawer">
151
+ <div class="sidebar-container">
152
+
153
+ <div class="sidebar-sticky"><a class="sidebar-brand" href="index">
154
+
155
+
156
+ <span class="sidebar-brand-text">Koffi</span>
157
+
158
+ </a><form class="sidebar-search-container" method="get" action="search" role="search">
159
+ <input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
160
+ <input type="hidden" name="check_keywords" value="yes">
161
+ <input type="hidden" name="area" value="default">
162
+ </form>
163
+ <div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
164
+ <ul class="current">
165
+ <li class="toctree-l1"><a class="reference internal" href="platforms">Requirements</a></li>
166
+ <li class="toctree-l1"><a class="reference internal" href="start">Quick start</a></li>
167
+ <li class="toctree-l1"><a class="reference internal" href="types">Data types</a></li>
168
+ <li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Functions</a></li>
169
+ <li class="toctree-l1"><a class="reference internal" href="memory">Memory usage</a></li>
170
+ <li class="toctree-l1"><a class="reference internal" href="benchmarks">Benchmarks</a></li>
171
+ <li class="toctree-l1"><a class="reference internal" href="contribute">Contributing</a></li>
172
+ <li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
173
+ </ul>
174
+
175
+ </div>
176
+ <div style="text-align: center; margin-top: 2em;">
177
+ <a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-2.O.1-brightgreen" alt="NPM"/></a>
178
+ <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
179
+ </div></div>
180
+
181
+ </div>
182
+
183
+ </div>
184
+ </aside>
185
+ <div class="main">
186
+ <div class="content">
187
+ <div class="article-container">
188
+ <a href="#" class="back-to-top muted-link">
189
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
190
+ <path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
191
+ </svg>
192
+ <span>Back to top</span>
193
+ </a>
194
+ <div class="content-icon-container">
195
+ <div class="theme-toggle-container theme-toggle-content">
196
+ <button class="theme-toggle">
197
+ <div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
198
+ <svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
199
+ <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
200
+ <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
201
+ </button>
202
+ </div>
203
+ <label class="toc-overlay-icon toc-content-icon" for="__toc">
204
+ <div class="visually-hidden">Toggle table of contents sidebar</div>
205
+ <i class="icon"><svg><use href="#svg-toc"></use></svg></i>
206
+ </label>
207
+ </div>
208
+ <article role="main">
209
+ <section id="functions">
210
+ <h1>Functions<a class="headerlink" href="#functions" title="Permalink to this heading">#</a></h1>
211
+ <section id="function-definitions">
212
+ <h2>Function definitions<a class="headerlink" href="#function-definitions" title="Permalink to this heading">#</a></h2>
213
+ <p>To declare functions, start by loading the shared library with <code class="docutils literal notranslate"><span class="pre">koffi.load(filename)</span></code>.</p>
214
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
215
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;/path/to/shared/library&#39;</span><span class="p">);</span> <span class="c1">// File extension depends on platforms: .so, .dll, .dylib, etc.</span>
216
+ </pre></div>
217
+ </div>
218
+ <p>You can use the returned object to load C functions from the library. To do so, you can use two syntaxes:</p>
219
+ <ul class="simple">
220
+ <li><p>The classic syntax, inspired by node-ffi</p></li>
221
+ <li><p>C-like prototypes</p></li>
222
+ </ul>
223
+ <section id="classic-syntax">
224
+ <h3>Classic syntax<a class="headerlink" href="#classic-syntax" title="Permalink to this heading">#</a></h3>
225
+ <p>To declare a function, you need to specify its non-mangled name, its return type, and its parameters. Use an ellipsis as the last parameter for variadic functions.</p>
226
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">printf</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;printf&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;...&#39;</span><span class="p">]);</span>
227
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">atoi</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;atoi&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">]);</span>
228
+ </pre></div>
229
+ </div>
230
+ <p>Koffi automatically tries mangled names for non-standard x86 calling conventions. See the section on <a class="reference internal" href="#calling-conventions"><span class="std std-doc">calling conventions</span></a> for more information on this subject.</p>
231
+ </section>
232
+ <section id="c-like-prototypes">
233
+ <h3>C-like prototypes<a class="headerlink" href="#c-like-prototypes" title="Permalink to this heading">#</a></h3>
234
+ <p>If you prefer, you can declare functions using simple C-like prototype strings, as shown below:</p>
235
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">printf</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int printf(const char *fmt, ...)&#39;</span><span class="p">);</span>
236
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">atoi</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int atoi(str)&#39;</span><span class="p">);</span> <span class="c1">// The parameter name is not used by Koffi, and optional</span>
237
+ </pre></div>
238
+ </div>
239
+ <p>You can use <code class="docutils literal notranslate"><span class="pre">()</span></code> or <code class="docutils literal notranslate"><span class="pre">(void)</span></code> for functions that take no argument.</p>
240
+ </section>
241
+ </section>
242
+ <section id="function-calls">
243
+ <h2>Function calls<a class="headerlink" href="#function-calls" title="Permalink to this heading">#</a></h2>
244
+ <section id="calling-conventions">
245
+ <h3>Calling conventions<a class="headerlink" href="#calling-conventions" title="Permalink to this heading">#</a></h3>
246
+ <p>By default, calling a C function happens synchronously.</p>
247
+ <p>Most architectures only support one procedure call standard per process. The 32-bit x86 platform is an exception to this, and Koffi supports several x86 conventions:</p>
248
+ <div class="table-wrapper colwidths-auto docutils container">
249
+ <table class="docutils align-default">
250
+ <thead>
251
+ <tr class="row-odd"><th class="head"><p>Convention</p></th>
252
+ <th class="head"><p>Classic form</p></th>
253
+ <th class="head"><p>Prototype form</p></th>
254
+ <th class="head"><p>Description</p></th>
255
+ </tr>
256
+ </thead>
257
+ <tbody>
258
+ <tr class="row-even"><td><p><strong>Cdecl</strong></p></td>
259
+ <td><p><code class="docutils literal notranslate"><span class="pre">koffi.cdecl</span></code> or <code class="docutils literal notranslate"><span class="pre">koffi.func</span></code></p></td>
260
+ <td><p><em>(default)</em></p></td>
261
+ <td><p>This is the default convention, and the only one on other platforms</p></td>
262
+ </tr>
263
+ <tr class="row-odd"><td><p><strong>Stdcall</strong></p></td>
264
+ <td><p><code class="docutils literal notranslate"><span class="pre">koffi.stdcall</span></code></p></td>
265
+ <td><p>__stdcall</p></td>
266
+ <td><p>This convention is used extensively within the Win32 API</p></td>
267
+ </tr>
268
+ <tr class="row-even"><td><p><strong>Fastcall</strong></p></td>
269
+ <td><p><code class="docutils literal notranslate"><span class="pre">koffi.fastcall</span></code></p></td>
270
+ <td><p>__fastcall</p></td>
271
+ <td><p>Rarely used, uses ECX and EDX for first two parameters</p></td>
272
+ </tr>
273
+ <tr class="row-odd"><td><p><strong>Thiscall</strong></p></td>
274
+ <td><p><code class="docutils literal notranslate"><span class="pre">koffi.thiscall</span></code></p></td>
275
+ <td><p>__thiscall</p></td>
276
+ <td><p>Rarely used, uses ECX for first parameter</p></td>
277
+ </tr>
278
+ </tbody>
279
+ </table>
280
+ </div>
281
+ <p>You can safely use these on non-x86 platforms, they are simply ignored.</p>
282
+ <p>Below you can find a small example showing how to use a non-default calling convention, with the two syntaxes:</p>
283
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
284
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;user32.dll&#39;</span><span class="p">);</span>
285
+ <span class="linenos">3</span>
286
+ <span class="linenos">4</span><span class="c1">// The following two declarations are equivalent, and use stdcall on x86 (and the default ABI on other platforms)</span>
287
+ <span class="linenos">5</span><span class="kd">const</span> <span class="nx">MessageBoxA_1</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">stdcall</span><span class="p">(</span><span class="s1">&#39;MessageBoxA&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;void *&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;uint&#39;</span><span class="p">]);</span>
288
+ <span class="linenos">6</span><span class="kd">const</span> <span class="nx">MessageBoxA_2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int __stdcall MessageBoxA(void *hwnd, str text, str caption, uint type)&#39;</span><span class="p">);</span>
289
+ </pre></div>
290
+ </div>
291
+ </section>
292
+ <section id="asynchronous-calls">
293
+ <h3>Asynchronous calls<a class="headerlink" href="#asynchronous-calls" title="Permalink to this heading">#</a></h3>
294
+ <p>You can issue asynchronous calls by calling the function through its async member. In this case, you need to provide a callback function as the last argument, with <code class="docutils literal notranslate"><span class="pre">(err,</span> <span class="pre">res)</span></code> parameters.</p>
295
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
296
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
297
+ <span class="linenos"> 3</span>
298
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">atoi</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int atoi(const char *str)&#39;</span><span class="p">);</span>
299
+ <span class="linenos"> 5</span>
300
+ <span class="linenos"> 6</span><span class="nx">atoi</span><span class="p">.</span><span class="k">async</span><span class="p">(</span><span class="s1">&#39;1257&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
301
+ <span class="linenos"> 7</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Result:&#39;</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
302
+ <span class="linenos"> 8</span><span class="p">})</span>
303
+ <span class="linenos"> 9</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Hello World!&#39;</span><span class="p">);</span>
304
+ <span class="linenos">10</span>
305
+ <span class="linenos">11</span><span class="c1">// This program will print:</span>
306
+ <span class="linenos">12</span><span class="c1">// Hello World!</span>
307
+ <span class="linenos">13</span><span class="c1">// Result: 1257</span>
308
+ </pre></div>
309
+ </div>
310
+ <p>These calls are executed by worker threads. It is <strong>your responsibility to deal with data sharing issues</strong> in the native code that may be caused by multi-threading.</p>
311
+ <p>You can easily convert this callback-style async function to a promise-based version with <code class="docutils literal notranslate"><span class="pre">util.promisify()</span></code> from the Node.js standard library.</p>
312
+ <p>Variadic functions cannot be called asynchronously.</p>
313
+ </section>
314
+ <section id="variadic-functions">
315
+ <h3>Variadic functions<a class="headerlink" href="#variadic-functions" title="Permalink to this heading">#</a></h3>
316
+ <p>Variadic functions are declared with an ellipsis as the last argument.</p>
317
+ <p>In order to call a variadic function, you must provide two Javascript arguments for each additional C parameter, the first one is the expected type and the second one is the value.</p>
318
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">printf</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;printf&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;...&#39;</span><span class="p">]);</span>
319
+ <span class="linenos">2</span>
320
+ <span class="linenos">3</span><span class="c1">// The variadic arguments are: 6 (int), 8.5 (double), &#39;THE END&#39; (const char *)</span>
321
+ <span class="linenos">4</span><span class="nx">printf</span><span class="p">(</span><span class="s1">&#39;Integer %d, double %g, str %s&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="mf">6</span><span class="p">,</span> <span class="s1">&#39;double&#39;</span><span class="p">,</span> <span class="mf">8.5</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;THE END&#39;</span><span class="p">);</span>
322
+ </pre></div>
323
+ </div>
324
+ <p>On x86 platforms, only the Cdecl convention can be used for variadic functions.</p>
325
+ </section>
326
+ </section>
327
+ <section id="special-considerations">
328
+ <h2>Special considerations<a class="headerlink" href="#special-considerations" title="Permalink to this heading">#</a></h2>
329
+ <section id="output-parameters">
330
+ <h3>Output parameters<a class="headerlink" href="#output-parameters" title="Permalink to this heading">#</a></h3>
331
+ <p>By default, Koffi will only forward arguments from Javascript to C. However, many C functions use pointer arguments for output values, or input/output values.</p>
332
+ <p>For simplicity, and because Javascript only has value semantics for primitive types, Koffi can marshal out (or in/out) two types of parameters:</p>
333
+ <ul class="simple">
334
+ <li><p><a class="reference internal" href="types#struct-types"><span class="std std-doc">Structs</span></a> (to/from JS objects)</p></li>
335
+ <li><p><a class="reference internal" href="types#opaque-types"><span class="std std-doc">Opaque types</span></a></p></li>
336
+ </ul>
337
+ <p>In order to change an argument from input-only to output or input/output, use the following functions:</p>
338
+ <ul class="simple">
339
+ <li><p><code class="docutils literal notranslate"><span class="pre">koffi.out()</span></code> on a pointer, e.g. <code class="docutils literal notranslate"><span class="pre">koffi.out(koffi.pointer(timeval))</span></code> (where timeval is a struct type)</p></li>
340
+ <li><p><code class="docutils literal notranslate"><span class="pre">koffi.inout()</span></code> for dual input/output parameters</p></li>
341
+ </ul>
342
+ <p>The same can be done when declaring a function with a C-like prototype string, with the MSDN-like type qualifiers:</p>
343
+ <ul class="simple">
344
+ <li><p><code class="docutils literal notranslate"><span class="pre">_Out_</span></code> for output parameters</p></li>
345
+ <li><p><code class="docutils literal notranslate"><span class="pre">_Inout_</span></code> for dual input/output parameters</p></li>
346
+ </ul>
347
+ <section id="struct-example">
348
+ <h4>Struct example<a class="headerlink" href="#struct-example" title="Permalink to this heading">#</a></h4>
349
+ <p>This example calls the POSIX function <code class="docutils literal notranslate"><span class="pre">gettimeofday()</span></code>, and uses the prototype-like syntax.</p>
350
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
351
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
352
+ <span class="linenos"> 3</span>
353
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">timeval</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">struct</span><span class="p">(</span><span class="s1">&#39;timeval&#39;</span><span class="p">,</span> <span class="p">{</span>
354
+ <span class="linenos"> 5</span> <span class="nx">tv_sec</span><span class="o">:</span> <span class="s1">&#39;unsigned int&#39;</span><span class="p">,</span>
355
+ <span class="linenos"> 6</span> <span class="nx">tv_usec</span><span class="o">:</span> <span class="s1">&#39;unsigned int&#39;</span>
356
+ <span class="linenos"> 7</span><span class="p">});</span>
357
+ <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">timezone</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">struct</span><span class="p">(</span><span class="s1">&#39;timezone&#39;</span><span class="p">,</span> <span class="p">{</span>
358
+ <span class="linenos"> 9</span> <span class="nx">tz_minuteswest</span><span class="o">:</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span>
359
+ <span class="linenos">10</span> <span class="nx">tz_dsttime</span><span class="o">:</span> <span class="s1">&#39;int&#39;</span>
360
+ <span class="linenos">11</span><span class="p">});</span>
361
+ <span class="linenos">12</span>
362
+ <span class="linenos">13</span><span class="c1">// The _Out_ qualifiers instruct Koffi to marshal out the values</span>
363
+ <span class="linenos">14</span><span class="kd">const</span> <span class="nx">gettimeofday</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int gettimeofday(_Out_ timeval *tv, _Out_ timezone *tz)&#39;</span><span class="p">);</span>
364
+ <span class="linenos">15</span>
365
+ <span class="linenos">16</span><span class="kd">let</span> <span class="nx">tv</span> <span class="o">=</span> <span class="p">{};</span>
366
+ <span class="linenos">17</span><span class="nx">gettimeofday</span><span class="p">(</span><span class="nx">tv</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
367
+ <span class="linenos">18</span>
368
+ <span class="linenos">19</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">tv</span><span class="p">);</span>
369
+ </pre></div>
370
+ </div>
371
+ </section>
372
+ <section id="opaque-type-example">
373
+ <h4>Opaque type example<a class="headerlink" href="#opaque-type-example" title="Permalink to this heading">#</a></h4>
374
+ <p>This example opens an in-memory SQLite database, and uses the node-ffi-style function declaration syntax.</p>
375
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
376
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;sqlite3.so&#39;</span><span class="p">);</span>
377
+ <span class="linenos"> 3</span>
378
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">sqlite3</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">opaque</span><span class="p">(</span><span class="s1">&#39;sqlite3&#39;</span><span class="p">);</span>
379
+ <span class="linenos"> 5</span>
380
+ <span class="linenos"> 6</span><span class="c1">// Use koffi.out() on a double pointer to copy out (from C to JS) after the call</span>
381
+ <span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">sqlite3_open_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_open_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">out</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3</span><span class="p">,</span> <span class="mf">2</span><span class="p">)),</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">]);</span>
382
+ <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">sqlite3_close_v2</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;sqlite3_close_v2&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">sqlite3</span><span class="p">)]);</span>
383
+ <span class="linenos"> 9</span>
384
+ <span class="linenos">10</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">=</span> <span class="mh">0x2</span><span class="p">;</span>
385
+ <span class="linenos">11</span><span class="kd">const</span> <span class="nx">SQLITE_OPEN_CREATE</span> <span class="o">=</span> <span class="mh">0x4</span><span class="p">;</span>
386
+ <span class="linenos">12</span>
387
+ <span class="linenos">13</span><span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="p">[</span><span class="kc">null</span><span class="p">];</span>
388
+ <span class="linenos">14</span><span class="k">if</span> <span class="p">(</span><span class="nx">sqlite3_open_v2</span><span class="p">(</span><span class="s1">&#39;:memory:&#39;</span><span class="p">,</span> <span class="nx">out</span><span class="p">,</span> <span class="nx">SQLITE_OPEN_READWRITE</span> <span class="o">|</span> <span class="nx">SQLITE_OPEN_CREATE</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span> <span class="o">!=</span> <span class="mf">0</span><span class="p">)</span>
389
+ <span class="linenos">15</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Failed to open database&#39;</span><span class="p">);</span>
390
+ <span class="linenos">16</span><span class="kd">let</span> <span class="nx">db</span> <span class="o">=</span> <span class="nx">out</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
391
+ <span class="linenos">17</span>
392
+ <span class="linenos">18</span><span class="nx">sqlite3_close_v2</span><span class="p">(</span><span class="nx">db</span><span class="p">);</span>
393
+ </pre></div>
394
+ </div>
395
+ </section>
396
+ </section>
397
+ <section id="polymorphic-parameters">
398
+ <h3>Polymorphic parameters<a class="headerlink" href="#polymorphic-parameters" title="Permalink to this heading">#</a></h3>
399
+ <p><em>New in Koffi 2.1</em></p>
400
+ <p>Many C functions use <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*</span></code> parameters in order to pass polymorphic objects and arrays, meaning that the data format changes can change depending on one other argument, or on some kind of struct tag member.</p>
401
+ <p>Koffi provides two features to deal with this:</p>
402
+ <ul class="simple">
403
+ <li><p>Typed JS arrays can be used as values in place everywhere <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*</span></code> is expected. See <a class="reference internal" href="types#array-pointers-dynamic-arrays"><span class="std std-doc">dynamic arrays</span></a> for more information, for input or output.</p></li>
404
+ <li><p>You can use <code class="docutils literal notranslate"><span class="pre">koffi.as(value,</span> <span class="pre">type)</span></code> to tell Koffi what kind of type is actually expected.</p></li>
405
+ </ul>
406
+ <p>The example below shows the use of <code class="docutils literal notranslate"><span class="pre">koffi.as()</span></code> to read the header of a PNG file with <code class="docutils literal notranslate"><span class="pre">fread()</span></code>.</p>
407
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
408
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
409
+ <span class="linenos"> 3</span>
410
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">FILE</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">opaque</span><span class="p">(</span><span class="s1">&#39;FILE&#39;</span><span class="p">);</span>
411
+ <span class="linenos"> 5</span>
412
+ <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">PngHeader</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pack</span><span class="p">(</span><span class="s1">&#39;PngHeader&#39;</span><span class="p">,</span> <span class="p">{</span>
413
+ <span class="linenos"> 7</span> <span class="nx">signature</span><span class="o">:</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">array</span><span class="p">(</span><span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span> <span class="mf">8</span><span class="p">),</span>
414
+ <span class="linenos"> 8</span> <span class="nx">ihdr</span><span class="o">:</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pack</span><span class="p">({</span>
415
+ <span class="linenos"> 9</span> <span class="nx">length</span><span class="o">:</span> <span class="s1">&#39;uint32_be_t&#39;</span><span class="p">,</span>
416
+ <span class="linenos">10</span> <span class="nx">chunk</span><span class="o">:</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">array</span><span class="p">(</span><span class="s1">&#39;char&#39;</span><span class="p">,</span> <span class="mf">4</span><span class="p">),</span>
417
+ <span class="linenos">11</span> <span class="nx">width</span><span class="o">:</span> <span class="s1">&#39;uint32_be_t&#39;</span><span class="p">,</span>
418
+ <span class="linenos">12</span> <span class="nx">height</span><span class="o">:</span> <span class="s1">&#39;uint32_be_t&#39;</span><span class="p">,</span>
419
+ <span class="linenos">13</span> <span class="nx">depth</span><span class="o">:</span> <span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span>
420
+ <span class="linenos">14</span> <span class="nx">color</span><span class="o">:</span> <span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span>
421
+ <span class="linenos">15</span> <span class="nx">compression</span><span class="o">:</span> <span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span>
422
+ <span class="linenos">16</span> <span class="nx">filter</span><span class="o">:</span> <span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span>
423
+ <span class="linenos">17</span> <span class="nx">interlace</span><span class="o">:</span> <span class="s1">&#39;uint8_t&#39;</span><span class="p">,</span>
424
+ <span class="linenos">18</span> <span class="nx">crc</span><span class="o">:</span> <span class="s1">&#39;uint32_be_t&#39;</span>
425
+ <span class="linenos">19</span> <span class="p">})</span>
426
+ <span class="linenos">20</span><span class="p">});</span>
427
+ <span class="linenos">21</span>
428
+ <span class="linenos">22</span><span class="kd">const</span> <span class="nx">fopen</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;FILE *fopen(const char *path, const char *mode)&#39;</span><span class="p">);</span>
429
+ <span class="linenos">23</span><span class="kd">const</span> <span class="nx">fclose</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;int fclose(FILE *fp)&#39;</span><span class="p">);</span>
430
+ <span class="linenos">24</span><span class="kd">const</span> <span class="nx">fread</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;size_t fread(_Out_ void *ptr, size_t size, size_t nmemb, FILE *fp)&#39;</span><span class="p">);</span>
431
+ <span class="linenos">25</span>
432
+ <span class="linenos">26</span><span class="kd">let</span> <span class="nx">filename</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">];</span>
433
+ <span class="linenos">27</span><span class="k">if</span> <span class="p">(</span><span class="nx">filename</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span>
434
+ <span class="linenos">28</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Usage: node png.js &lt;image.png&gt;&#39;</span><span class="p">);</span>
435
+ <span class="linenos">29</span>
436
+ <span class="linenos">30</span><span class="kd">let</span> <span class="nx">hdr</span> <span class="o">=</span> <span class="p">{};</span>
437
+ <span class="linenos">31</span><span class="p">{</span>
438
+ <span class="linenos">32</span>
439
+ <span class="linenos">33</span> <span class="kd">let</span> <span class="nx">fp</span> <span class="o">=</span> <span class="nx">fopen</span><span class="p">(</span><span class="nx">filename</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">);</span>
440
+ <span class="linenos">34</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">fp</span><span class="p">)</span>
441
+ <span class="linenos">35</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="sb">`Failed to open &#39;</span><span class="si">${</span><span class="nx">filename</span><span class="si">}</span><span class="sb">&#39;`</span><span class="p">);</span>
442
+ <span class="linenos">36</span>
443
+ <span class="linenos">37</span> <span class="k">try</span> <span class="p">{</span>
444
+ <span class="linenos">38</span> <span class="kd">let</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">fread</span><span class="p">(</span><span class="nx">koffi</span><span class="p">.</span><span class="kr">as</span><span class="p">(</span><span class="nx">hdr</span><span class="p">,</span> <span class="s1">&#39;PngHeader *&#39;</span><span class="p">),</span> <span class="mf">1</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">sizeof</span><span class="p">(</span><span class="nx">PngHeader</span><span class="p">),</span> <span class="nx">fp</span><span class="p">);</span>
445
+ <span class="linenos">39</span> <span class="k">if</span> <span class="p">(</span><span class="nx">len</span> <span class="o">&lt;</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">sizeof</span><span class="p">(</span><span class="nx">PngHeader</span><span class="p">))</span>
446
+ <span class="linenos">40</span> <span class="k">throw</span> <span class="ow">new</span> <span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Failed to read PNG header&#39;</span><span class="p">);</span>
447
+ <span class="linenos">41</span> <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
448
+ <span class="linenos">42</span> <span class="nx">fclose</span><span class="p">(</span><span class="nx">fp</span><span class="p">);</span>
449
+ <span class="linenos">43</span> <span class="p">}</span>
450
+ <span class="linenos">44</span><span class="p">}</span>
451
+ <span class="linenos">45</span>
452
+ <span class="linenos">46</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;PNG header:&#39;</span><span class="p">,</span> <span class="nx">hdr</span><span class="p">);</span>
453
+ </pre></div>
454
+ </div>
455
+ </section>
456
+ <section id="heap-allocated-values">
457
+ <h3>Heap-allocated values<a class="headerlink" href="#heap-allocated-values" title="Permalink to this heading">#</a></h3>
458
+ <p><em>New in Koffi 2.0</em></p>
459
+ <p>Some C functions return heap-allocated values directly or through output parameters. While Koffi automatically converts values from C to JS (to a string or an object), it does not know when something needs to be freed, or how.</p>
460
+ <p>For opaque types, such as FILE, this does not matter because you will explicitly call <code class="docutils literal notranslate"><span class="pre">fclose()</span></code> on them. But some values (such as strings) get implicitly converted by Koffi, and you lose access to the original pointer. This creates a leak if the string is heap-allocated.</p>
461
+ <p>To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a <strong>disposable type</strong> with <code class="docutils literal notranslate"><span class="pre">koffi.dispose(name,</span> <span class="pre">type,</span> <span class="pre">func)</span></code>. This creates a type derived from another type, the only difference being that <em>func</em> gets called with the original pointer once the value has been converted and is not needed anymore.</p>
462
+ <p>The <em>name</em> can be omitted to create an anonymous disposable type. If <em>func</em> is omitted or is null, Koffi will use <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code> (which calls the standard C library <em>free</em> function under the hood).</p>
463
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">AnonHeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;str&#39;</span><span class="p">);</span> <span class="c1">// Anonymous type (cannot be used in function prototypes)</span>
464
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">NamedHeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;HeapStr&#39;</span><span class="p">,</span> <span class="s1">&#39;str&#39;</span><span class="p">);</span> <span class="c1">// Same thing, but named so usable in function prototypes</span>
465
+ <span class="linenos">3</span><span class="kd">const</span> <span class="nx">ExplicitFree</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;HeapStr16&#39;</span><span class="p">,</span> <span class="s1">&#39;str16&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">free</span><span class="p">);</span> <span class="c1">// You can specify any other JS function</span>
466
+ </pre></div>
467
+ </div>
468
+ <p>The following example illustrates the use of a disposable type derived from <em>str</em>.</p>
469
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
470
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
471
+ <span class="linenos">3</span>
472
+ <span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func(&#39;const char *! strdup(const char *str)&#39;)</span>
473
+ <span class="linenos">5</span><span class="kd">const</span> <span class="nx">HeapStr</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">disposable</span><span class="p">(</span><span class="s1">&#39;str&#39;</span><span class="p">);</span>
474
+ <span class="linenos">6</span><span class="kd">const</span> <span class="nx">strdup</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">cdecl</span><span class="p">(</span><span class="s1">&#39;strdup&#39;</span><span class="p">,</span> <span class="nx">HeapStr</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">]);</span>
475
+ <span class="linenos">7</span>
476
+ <span class="linenos">8</span><span class="kd">let</span> <span class="nx">copy</span> <span class="o">=</span> <span class="nx">strdup</span><span class="p">(</span><span class="s1">&#39;Hello!&#39;</span><span class="p">);</span>
477
+ <span class="linenos">9</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">copy</span><span class="p">);</span> <span class="c1">// Prints Hello!</span>
478
+ </pre></div>
479
+ </div>
480
+ <p>When you declare functions with the <a class="reference internal" href="#c-like-prototypes"><span class="std std-doc">prototype-like syntax</span></a>, you can either use named disposable types or use the ‘!’ shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls <code class="docutils literal notranslate"><span class="pre">koffi.free(ptr)</span></code>.</p>
481
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
482
+ <span class="linenos">2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;libc.so.6&#39;</span><span class="p">);</span>
483
+ <span class="linenos">3</span>
484
+ <span class="linenos">4</span><span class="c1">// You can also use: const strdup = lib.func(&#39;const char *! strdup(const char *str)&#39;)</span>
485
+ <span class="linenos">5</span><span class="kd">const</span> <span class="nx">strdup</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;str! strdup(const char *str)&#39;</span><span class="p">);</span>
486
+ <span class="linenos">6</span>
487
+ <span class="linenos">7</span><span class="kd">let</span> <span class="nx">copy</span> <span class="o">=</span> <span class="nx">strdup</span><span class="p">(</span><span class="s1">&#39;World!&#39;</span><span class="p">);</span>
488
+ <span class="linenos">8</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">copy</span><span class="p">);</span> <span class="c1">// Prints World!</span>
489
+ </pre></div>
490
+ </div>
491
+ <p>Disposable types can only be created from pointer or string types.</p>
492
+ <div class="admonition warning">
493
+ <p class="admonition-title">Warning</p>
494
+ <p>Be careful on Windows: if your shared library uses a different CRT (such as msvcrt), the memory could have been allocated by a different malloc/free implementation or heap, resulting in undefined behavior if you use <code class="docutils literal notranslate"><span class="pre">koffi.free()</span></code>.</p>
495
+ </div>
496
+ </section>
497
+ </section>
498
+ <section id="javascript-callbacks">
499
+ <h2>Javascript callbacks<a class="headerlink" href="#javascript-callbacks" title="Permalink to this heading">#</a></h2>
500
+ <p>In order to pass a JS function to a C function expecting a callback, you must first create a callback type with the expected return type and parameters. The syntax is similar to the one used to load functions from a shared library.</p>
501
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
502
+ <span class="linenos">2</span>
503
+ <span class="linenos">3</span><span class="c1">// With the classic syntax, this callback expects an integer and returns nothing</span>
504
+ <span class="linenos">4</span><span class="kd">const</span> <span class="nx">ExampleCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;ExampleCallback&#39;</span><span class="p">,</span> <span class="s1">&#39;void&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;int&#39;</span><span class="p">]);</span>
505
+ <span class="linenos">5</span>
506
+ <span class="linenos">6</span><span class="c1">// With the prototype parser, this callback expects a double and float, and returns the sum as a double</span>
507
+ <span class="linenos">7</span><span class="kd">const</span> <span class="nx">AddDoubleFloat</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;double AddDoubleFloat(double d, float f)&#39;</span><span class="p">);</span>
508
+ </pre></div>
509
+ </div>
510
+ <p>Once your callback type is declared, you can use a pointer to it in struct definitions, or as function parameters and/or return types.</p>
511
+ <div class="admonition note">
512
+ <p class="admonition-title">Note</p>
513
+ <p>Callbacks <strong>have changed in version 2.0</strong>.</p>
514
+ <p>In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.</p>
515
+ <p>Now, you must use them through a pointer: <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">CallIt(CallbackType</span> <span class="pre">func)</span></code> in Koffi 1.x becomes <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">CallIt(CallbackType</span> <span class="pre">*func)</span></code> in version 2.0 and newer.</p>
516
+ <p>Consult the <a class="reference internal" href="changes"><span class="doc std std-doc">migration guide</span></a> for more information.</p>
517
+ </div>
518
+ <p>Koffi only uses predefined static trampolines, and does not need to generate code at runtime, which makes it compatible with platforms with hardened W^X migitations (such as PaX mprotect). However, this imposes some restrictions on the maximum number of callbacks, and their duration.</p>
519
+ <p>Thus, Koffi distinguishes two callback modes:</p>
520
+ <ul class="simple">
521
+ <li><p><a class="reference internal" href="#transient-callbacks"><span class="std std-doc">Transient callbacks</span></a> can only be called while the C function they are passed to is running, and are invalidated when it returns. If the C function calls the callback later, the behavior is undefined, though Koffi tries to detect such cases. If it does, an exception will be thrown, but this is no guaranteed. However, they are simple to use, and don’t require any special handling.</p></li>
522
+ <li><p><a class="reference internal" href="#registered-callbacks"><span class="std std-doc">Registered callbacks</span></a> can be called at any time, but they must be manually registered and unregistered. A limited number of registered callbacks can exist at the same time.</p></li>
523
+ </ul>
524
+ <p>You need to specify the correct <a class="reference internal" href="#calling-conventions"><span class="std std-doc">calling convention</span></a> on x86 platforms, or the behavior is undefined (Node will probably crash). Only <em>cdecl</em> and <em>stdcall</em> callbacks are supported.</p>
525
+ <section id="transient-callbacks">
526
+ <h3>Transient callbacks<a class="headerlink" href="#transient-callbacks" title="Permalink to this heading">#</a></h3>
527
+ <p>Use transient callbacks when the native C function only needs to call them while it runs (e.g. qsort, progress callback, <code class="docutils literal notranslate"><span class="pre">sqlite3_exec</span></code>). Here is a small example with the C part and the JS part.</p>
528
+ <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
529
+ <span class="linenos">2</span>
530
+ <span class="linenos">3</span><span class="kt">int</span><span class="w"> </span><span class="nf">TransferToJS</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">age</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">cb</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">str</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">age</span><span class="p">))</span><span class="w"></span>
531
+ <span class="linenos">4</span><span class="p">{</span><span class="w"></span>
532
+ <span class="linenos">5</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">buf</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span><span class="w"></span>
533
+ <span class="linenos">6</span><span class="w"> </span><span class="n">snprintf</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">buf</span><span class="p">),</span><span class="w"> </span><span class="s">&quot;Hello %s!&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">str</span><span class="p">);</span><span class="w"></span>
534
+ <span class="linenos">7</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">cb</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="n">age</span><span class="p">);</span><span class="w"></span>
535
+ <span class="linenos">8</span><span class="p">}</span><span class="w"></span>
536
+ </pre></div>
537
+ </div>
538
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
539
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;./callbacks.so&#39;</span><span class="p">);</span> <span class="c1">// Fake path</span>
540
+ <span class="linenos"> 3</span>
541
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">TransferCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;int TransferCallback(const char *str, int age)&#39;</span><span class="p">);</span>
542
+ <span class="linenos"> 5</span>
543
+ <span class="linenos"> 6</span><span class="kd">const</span> <span class="nx">TransferToJS</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;TransferToJS&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;str&#39;</span><span class="p">,</span> <span class="s1">&#39;int&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">TransferCallback</span><span class="p">)]);</span>
544
+ <span class="linenos"> 7</span>
545
+ <span class="linenos"> 8</span><span class="kd">let</span> <span class="nx">ret</span> <span class="o">=</span> <span class="nx">TransferToJS</span><span class="p">(</span><span class="s1">&#39;Niels&#39;</span><span class="p">,</span> <span class="mf">27</span><span class="p">,</span> <span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
546
+ <span class="linenos"> 9</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
547
+ <span class="linenos">10</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Your age is:&#39;</span><span class="p">,</span> <span class="nx">age</span><span class="p">);</span>
548
+ <span class="linenos">11</span> <span class="k">return</span> <span class="mf">42</span><span class="p">;</span>
549
+ <span class="linenos">12</span><span class="p">});</span>
550
+ <span class="linenos">13</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ret</span><span class="p">);</span>
551
+ <span class="linenos">14</span>
552
+ <span class="linenos">15</span><span class="c1">// This example prints:</span>
553
+ <span class="linenos">16</span><span class="c1">// Hello Niels!</span>
554
+ <span class="linenos">17</span><span class="c1">// Your age is: 27</span>
555
+ <span class="linenos">18</span><span class="c1">// 42</span>
556
+ </pre></div>
557
+ </div>
558
+ </section>
559
+ <section id="registered-callbacks">
560
+ <h3>Registered callbacks<a class="headerlink" href="#registered-callbacks" title="Permalink to this heading">#</a></h3>
561
+ <p><em>New in Koffi 2.0</em></p>
562
+ <p>Use registered callbacks when the function needs to be called at a later time (e.g. log handler, event handler, <code class="docutils literal notranslate"><span class="pre">fopencookie/funopen</span></code>). Call <code class="docutils literal notranslate"><span class="pre">koffi.register(func,</span> <span class="pre">type)</span></code> to register a callback function, with two arguments: the JS function, and the callback type.</p>
563
+ <p>When you are done, call <code class="docutils literal notranslate"><span class="pre">koffi.unregister()</span></code> (with the value returned by <code class="docutils literal notranslate"><span class="pre">koffi.register()</span></code>) to release the slot. A maximum of 16 registered callbacks can exist at the same time. Failure to do so will leak the slot, and subsequent registrations may fail (with an exception) once all slots are used.</p>
564
+ <p>The example below shows how to register and unregister delayed callbacks.</p>
565
+ <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="k">static</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">g_cb1</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">);</span><span class="w"></span>
566
+ <span class="linenos"> 2</span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">g_cb2</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">str</span><span class="p">);</span><span class="w"></span>
567
+ <span class="linenos"> 3</span>
568
+ <span class="linenos"> 4</span><span class="kt">void</span><span class="w"> </span><span class="nf">RegisterFunctions</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">cb1</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">),</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">cb2</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">str</span><span class="p">))</span><span class="w"></span>
569
+ <span class="linenos"> 5</span><span class="p">{</span><span class="w"></span>
570
+ <span class="linenos"> 6</span><span class="w"> </span><span class="n">g_cb1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cb1</span><span class="p">;</span><span class="w"></span>
571
+ <span class="linenos"> 7</span><span class="w"> </span><span class="n">g_cb2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cb2</span><span class="p">;</span><span class="w"></span>
572
+ <span class="linenos"> 8</span><span class="p">}</span><span class="w"></span>
573
+ <span class="linenos"> 9</span>
574
+ <span class="linenos">10</span><span class="kt">void</span><span class="w"> </span><span class="nf">SayIt</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">)</span><span class="w"></span>
575
+ <span class="linenos">11</span><span class="p">{</span><span class="w"></span>
576
+ <span class="linenos">12</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">str</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">g_cb1</span><span class="p">(</span><span class="n">name</span><span class="p">);</span><span class="w"></span>
577
+ <span class="linenos">13</span><span class="w"> </span><span class="n">g_cb2</span><span class="p">(</span><span class="n">str</span><span class="p">);</span><span class="w"></span>
578
+ <span class="linenos">14</span><span class="p">}</span><span class="w"></span>
579
+ </pre></div>
580
+ </div>
581
+ <div class="highlight-js notranslate"><div class="highlight"><pre><span></span><span class="linenos"> 1</span><span class="kd">const</span> <span class="nx">koffi</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;koffi&#39;</span><span class="p">);</span>
582
+ <span class="linenos"> 2</span><span class="kd">const</span> <span class="nx">lib</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="s1">&#39;./callbacks.so&#39;</span><span class="p">);</span> <span class="c1">// Fake path</span>
583
+ <span class="linenos"> 3</span>
584
+ <span class="linenos"> 4</span><span class="kd">const</span> <span class="nx">GetCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;const char *GetCallback(const char *name)&#39;</span><span class="p">);</span>
585
+ <span class="linenos"> 5</span><span class="kd">const</span> <span class="nx">PrintCallback</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">callback</span><span class="p">(</span><span class="s1">&#39;void PrintCallback(const char *str)&#39;</span><span class="p">);</span>
586
+ <span class="linenos"> 6</span>
587
+ <span class="linenos"> 7</span><span class="kd">const</span> <span class="nx">RegisterFunctions</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;void RegisterFunctions(GetCallback *cb1, PrintCallback *cb2)&#39;</span><span class="p">);</span>
588
+ <span class="linenos"> 8</span><span class="kd">const</span> <span class="nx">SayIt</span> <span class="o">=</span> <span class="nx">lib</span><span class="p">.</span><span class="nx">func</span><span class="p">(</span><span class="s1">&#39;void SayIt(const char *name)&#39;</span><span class="p">);</span>
589
+ <span class="linenos"> 9</span>
590
+ <span class="linenos">10</span><span class="kd">let</span> <span class="nx">cb1</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">name</span> <span class="p">=&gt;</span> <span class="s1">&#39;Hello &#39;</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">pointer</span><span class="p">(</span><span class="nx">GetCallback</span><span class="p">));</span>
591
+ <span class="linenos">11</span><span class="kd">let</span> <span class="nx">cb2</span> <span class="o">=</span> <span class="nx">koffi</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">,</span> <span class="s1">&#39;PrintCallback *&#39;</span><span class="p">);</span>
592
+ <span class="linenos">12</span>
593
+ <span class="linenos">13</span><span class="nx">RegisterFunctions</span><span class="p">(</span><span class="nx">cb1</span><span class="p">,</span> <span class="nx">cb2</span><span class="p">);</span>
594
+ <span class="linenos">14</span><span class="nx">SayIt</span><span class="p">(</span><span class="s1">&#39;Kyoto&#39;</span><span class="p">);</span> <span class="c1">// Prints Hello Kyoto!</span>
595
+ <span class="linenos">15</span>
596
+ <span class="linenos">16</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">unregister</span><span class="p">(</span><span class="nx">cb1</span><span class="p">);</span>
597
+ <span class="linenos">17</span><span class="nx">koffi</span><span class="p">.</span><span class="nx">unregister</span><span class="p">(</span><span class="nx">cb2</span><span class="p">);</span>
598
+ </pre></div>
599
+ </div>
600
+ </section>
601
+ <section id="handling-of-exceptions">
602
+ <h3>Handling of exceptions<a class="headerlink" href="#handling-of-exceptions" title="Permalink to this heading">#</a></h3>
603
+ <p>If an exception happens inside the JS callback, the C API will receive 0 or NULL (depending on the return value type).</p>
604
+ <p>Handle the exception yourself (with try/catch) if you need to handle exceptions differently.</p>
605
+ </section>
606
+ </section>
607
+ <section id="thread-safety">
608
+ <h2>Thread safety<a class="headerlink" href="#thread-safety" title="Permalink to this heading">#</a></h2>
609
+ <p>Asynchronous functions run on worker threads. You need to deal with thread safety issues if you share data between threads.</p>
610
+ <p>Callbacks must be called from the main thread, or more precisely from the same thread as the V8 intepreter. Calling a callback from another thread is undefined behavior, and will likely lead to a crash or a big mess. You’ve been warned!</p>
611
+ </section>
612
+ </section>
613
+
614
+ </article>
615
+ </div>
616
+ <footer>
617
+
618
+ <div class="related-pages">
619
+ <a class="next-page" href="memory">
620
+ <div class="page-info">
621
+ <div class="context">
622
+ <span>Next</span>
623
+ </div>
624
+ <div class="title">Memory usage</div>
625
+ </div>
626
+ <svg><use href="#svg-arrow-right"></use></svg>
627
+ </a>
628
+ <a class="prev-page" href="types">
629
+ <svg><use href="#svg-arrow-right"></use></svg>
630
+ <div class="page-info">
631
+ <div class="context">
632
+ <span>Previous</span>
633
+ </div>
634
+
635
+ <div class="title">Data types</div>
636
+
637
+ </div>
638
+ </a>
639
+ </div>
640
+ <div class="bottom-of-page">
641
+ <div class="left-details">
642
+ <div class="copyright">
643
+ Copyright &#169; 2022, Niels Martignène
644
+ </div>
645
+ Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
646
+
647
+ <a href="https://github.com/pradyunsg/furo">Furo</a>
648
+
649
+ </div>
650
+ <div class="right-details">
651
+ <div class="icons">
652
+
653
+ </div>
654
+ </div>
655
+ </div>
656
+
657
+ </footer>
658
+ </div>
659
+ <aside class="toc-drawer">
660
+
661
+
662
+ <div class="toc-sticky toc-scroll">
663
+ <div class="toc-title-container">
664
+ <span class="toc-title">
665
+ Contents
666
+ </span>
667
+ </div>
668
+ <div class="toc-tree-container">
669
+ <div class="toc-tree">
670
+ <ul>
671
+ <li><a class="reference internal" href="#">Functions</a><ul>
672
+ <li><a class="reference internal" href="#function-definitions">Function definitions</a><ul>
673
+ <li><a class="reference internal" href="#classic-syntax">Classic syntax</a></li>
674
+ <li><a class="reference internal" href="#c-like-prototypes">C-like prototypes</a></li>
675
+ </ul>
676
+ </li>
677
+ <li><a class="reference internal" href="#function-calls">Function calls</a><ul>
678
+ <li><a class="reference internal" href="#calling-conventions">Calling conventions</a></li>
679
+ <li><a class="reference internal" href="#asynchronous-calls">Asynchronous calls</a></li>
680
+ <li><a class="reference internal" href="#variadic-functions">Variadic functions</a></li>
681
+ </ul>
682
+ </li>
683
+ <li><a class="reference internal" href="#special-considerations">Special considerations</a><ul>
684
+ <li><a class="reference internal" href="#output-parameters">Output parameters</a><ul>
685
+ <li><a class="reference internal" href="#struct-example">Struct example</a></li>
686
+ <li><a class="reference internal" href="#opaque-type-example">Opaque type example</a></li>
687
+ </ul>
688
+ </li>
689
+ <li><a class="reference internal" href="#polymorphic-parameters">Polymorphic parameters</a></li>
690
+ <li><a class="reference internal" href="#heap-allocated-values">Heap-allocated values</a></li>
691
+ </ul>
692
+ </li>
693
+ <li><a class="reference internal" href="#javascript-callbacks">Javascript callbacks</a><ul>
694
+ <li><a class="reference internal" href="#transient-callbacks">Transient callbacks</a></li>
695
+ <li><a class="reference internal" href="#registered-callbacks">Registered callbacks</a></li>
696
+ <li><a class="reference internal" href="#handling-of-exceptions">Handling of exceptions</a></li>
697
+ </ul>
698
+ </li>
699
+ <li><a class="reference internal" href="#thread-safety">Thread safety</a></li>
700
+ </ul>
701
+ </li>
702
+ </ul>
703
+
704
+ </div>
705
+ </div>
706
+ </div>
707
+
708
+
709
+ </aside>
710
+ </div>
711
+ </div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
712
+ <script src="_static/jquery.js"></script>
713
+ <script src="_static/underscore.js"></script>
714
+ <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
715
+ <script src="_static/doctools.js"></script>
716
+ <script src="_static/scripts/furo.js"></script>
717
+ </body>
718
+ </html>