koffi 2.1.0-beta.1 → 2.1.0

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 (257) hide show
  1. package/CMakeLists.txt +1 -1
  2. package/ChangeLog.md +18 -0
  3. package/build/qemu/2.1.0/koffi_darwin_arm64.tar.gz +0 -0
  4. package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
  5. package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
  6. package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
  7. package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
  8. package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
  9. package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
  10. package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
  11. package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  12. package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
  13. package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
  14. package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
  15. package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
  16. package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
  17. package/build/qemu/2.1.0/koffi_win32_x64.tar.gz +0 -0
  18. package/doc/Makefile +1 -1
  19. package/doc/benchmarks.md +14 -14
  20. package/doc/benchmarks.xlsx +0 -0
  21. package/doc/conf.py +5 -0
  22. package/doc/functions.md +67 -1
  23. package/doc/index.rst +2 -2
  24. package/doc/make.bat +1 -1
  25. package/doc/static/perf_linux_20220812.png +0 -0
  26. package/doc/static/perf_windows_20220812.png +0 -0
  27. package/doc/templates/badges.html +1 -2
  28. package/doc/types.md +112 -159
  29. package/package.json +2 -1
  30. package/qemu/registry/machines.json +2 -2
  31. package/qemu/registry/sha256sum.txt +2 -2
  32. package/src/abi_arm32.cc +224 -150
  33. package/src/abi_arm64.cc +255 -103
  34. package/src/abi_riscv64.cc +144 -88
  35. package/src/abi_x64_sysv.cc +151 -89
  36. package/src/abi_x64_win.cc +150 -88
  37. package/src/abi_x86.cc +198 -115
  38. package/src/call.cc +310 -137
  39. package/src/call.hh +4 -4
  40. package/src/ffi.cc +64 -20
  41. package/src/ffi.hh +12 -0
  42. package/src/util.hh +0 -20
  43. package/test/callbacks.js +3 -3
  44. package/test/misc.c +45 -2
  45. package/test/sync.js +83 -2
  46. package/vendor/libcc/libcc.cc +75 -55
  47. package/vendor/libcc/libcc.hh +306 -255
  48. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +226 -0
  49. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +10 -0
  50. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +4 -0
  51. package/vendor/raylib/projects/VS2019-Android/raylib_android.sln +75 -0
  52. package/vendor/raylib/projects/VS2022/examples/audio_module_playing.vcxproj +390 -0
  53. package/vendor/raylib/projects/VS2022/examples/audio_multichannel_sound.vcxproj +390 -0
  54. package/vendor/raylib/projects/VS2022/examples/audio_music_stream.vcxproj +390 -0
  55. package/vendor/raylib/projects/VS2022/examples/audio_raw_stream.vcxproj +390 -0
  56. package/vendor/raylib/projects/VS2022/examples/audio_sound_loading.vcxproj +390 -0
  57. package/vendor/raylib/projects/VS2022/examples/audio_stream_effects.vcxproj +390 -0
  58. package/vendor/raylib/projects/VS2022/examples/core_2d_camera.vcxproj +390 -0
  59. package/vendor/raylib/projects/VS2022/examples/core_2d_camera_mouse_zoom.vcxproj +390 -0
  60. package/vendor/raylib/projects/VS2022/examples/core_2d_camera_platformer.vcxproj +390 -0
  61. package/vendor/raylib/projects/VS2022/examples/core_3d_camera_first_person.vcxproj +390 -0
  62. package/vendor/raylib/projects/VS2022/examples/core_3d_camera_free.vcxproj +390 -0
  63. package/vendor/raylib/projects/VS2022/examples/core_3d_camera_mode.vcxproj +390 -0
  64. package/vendor/raylib/projects/VS2022/examples/core_3d_picking.vcxproj +390 -0
  65. package/vendor/raylib/projects/VS2022/examples/core_basic_screen_manager.vcxproj +390 -0
  66. package/vendor/raylib/projects/VS2022/examples/core_basic_window.vcxproj +390 -0
  67. package/vendor/raylib/projects/VS2022/examples/core_custom_frame_control.vcxproj +390 -0
  68. package/vendor/raylib/projects/VS2022/examples/core_custom_logging.vcxproj +390 -0
  69. package/vendor/raylib/projects/VS2022/examples/core_drop_files.vcxproj +390 -0
  70. package/vendor/raylib/projects/VS2022/examples/core_input_gamepad.vcxproj +387 -0
  71. package/vendor/raylib/projects/VS2022/examples/core_input_gestures.vcxproj +387 -0
  72. package/vendor/raylib/projects/VS2022/examples/core_input_keys.vcxproj +387 -0
  73. package/vendor/raylib/projects/VS2022/examples/core_input_mouse.vcxproj +387 -0
  74. package/vendor/raylib/projects/VS2022/examples/core_input_mouse_wheel.vcxproj +387 -0
  75. package/vendor/raylib/projects/VS2022/examples/core_input_multitouch.vcxproj +387 -0
  76. package/vendor/raylib/projects/VS2022/examples/core_loading_thread.vcxproj +387 -0
  77. package/vendor/raylib/projects/VS2022/examples/core_random_values.vcxproj +387 -0
  78. package/vendor/raylib/projects/VS2022/examples/core_scissor_test.vcxproj +387 -0
  79. package/vendor/raylib/projects/VS2022/examples/core_split_screen.vcxproj +387 -0
  80. package/vendor/raylib/projects/VS2022/examples/core_storage_values.vcxproj +387 -0
  81. package/vendor/raylib/projects/VS2022/examples/core_vr_simulator.vcxproj +387 -0
  82. package/vendor/raylib/projects/VS2022/examples/core_window_flags.vcxproj +387 -0
  83. package/vendor/raylib/projects/VS2022/examples/core_window_letterbox.vcxproj +387 -0
  84. package/vendor/raylib/projects/VS2022/examples/core_window_should_close.vcxproj +390 -0
  85. package/vendor/raylib/projects/VS2022/examples/core_world_screen.vcxproj +387 -0
  86. package/vendor/raylib/projects/VS2022/examples/easings_testbed.vcxproj +387 -0
  87. package/vendor/raylib/projects/VS2022/examples/embedded_files_loading.vcxproj +387 -0
  88. package/vendor/raylib/projects/VS2022/examples/models_animation.vcxproj +387 -0
  89. package/vendor/raylib/projects/VS2022/examples/models_billboard.vcxproj +387 -0
  90. package/vendor/raylib/projects/VS2022/examples/models_box_collisions.vcxproj +387 -0
  91. package/vendor/raylib/projects/VS2022/examples/models_cubicmap.vcxproj +387 -0
  92. package/vendor/raylib/projects/VS2022/examples/models_first_person_maze.vcxproj +387 -0
  93. package/vendor/raylib/projects/VS2022/examples/models_geometric_shapes.vcxproj +387 -0
  94. package/vendor/raylib/projects/VS2022/examples/models_heightmap.vcxproj +387 -0
  95. package/vendor/raylib/projects/VS2022/examples/models_loading.vcxproj +387 -0
  96. package/vendor/raylib/projects/VS2022/examples/models_loading_gltf.vcxproj +387 -0
  97. package/vendor/raylib/projects/VS2022/examples/models_loading_vox.vcxproj +387 -0
  98. package/vendor/raylib/projects/VS2022/examples/models_mesh_generation.vcxproj +387 -0
  99. package/vendor/raylib/projects/VS2022/examples/models_mesh_picking.vcxproj +387 -0
  100. package/vendor/raylib/projects/VS2022/examples/models_orthographic_projection.vcxproj +387 -0
  101. package/vendor/raylib/projects/VS2022/examples/models_rlgl_solar_system.vcxproj +387 -0
  102. package/vendor/raylib/projects/VS2022/examples/models_skybox.vcxproj +387 -0
  103. package/vendor/raylib/projects/VS2022/examples/models_waving_cubes.vcxproj +387 -0
  104. package/vendor/raylib/projects/VS2022/examples/models_yaw_pitch_roll.vcxproj +387 -0
  105. package/vendor/raylib/projects/VS2022/examples/rlgl_compute_shaders.vcxproj +391 -0
  106. package/vendor/raylib/projects/VS2022/examples/rlgl_standalone.vcxproj +391 -0
  107. package/vendor/raylib/projects/VS2022/examples/shaders_basic_lighting.vcxproj +387 -0
  108. package/vendor/raylib/projects/VS2022/examples/shaders_custom_uniform.vcxproj +387 -0
  109. package/vendor/raylib/projects/VS2022/examples/shaders_eratosthenes.vcxproj +387 -0
  110. package/vendor/raylib/projects/VS2022/examples/shaders_fog.vcxproj +387 -0
  111. package/vendor/raylib/projects/VS2022/examples/shaders_hot_reloading.vcxproj +387 -0
  112. package/vendor/raylib/projects/VS2022/examples/shaders_julia_set.vcxproj +387 -0
  113. package/vendor/raylib/projects/VS2022/examples/shaders_mesh_instancing.vcxproj +387 -0
  114. package/vendor/raylib/projects/VS2022/examples/shaders_model_shader.vcxproj +387 -0
  115. package/vendor/raylib/projects/VS2022/examples/shaders_multi_sample2d.vcxproj +387 -0
  116. package/vendor/raylib/projects/VS2022/examples/shaders_palette_switch.vcxproj +387 -0
  117. package/vendor/raylib/projects/VS2022/examples/shaders_postprocessing.vcxproj +387 -0
  118. package/vendor/raylib/projects/VS2022/examples/shaders_raymarching.vcxproj +387 -0
  119. package/vendor/raylib/projects/VS2022/examples/shaders_shapes_textures.vcxproj +387 -0
  120. package/vendor/raylib/projects/VS2022/examples/shaders_simple_mask.vcxproj +387 -0
  121. package/vendor/raylib/projects/VS2022/examples/shaders_spotlight.vcxproj +387 -0
  122. package/vendor/raylib/projects/VS2022/examples/shaders_texture_drawing.vcxproj +387 -0
  123. package/vendor/raylib/projects/VS2022/examples/shaders_texture_waves.vcxproj +387 -0
  124. package/vendor/raylib/projects/VS2022/examples/shapes_basic_shapes.vcxproj +387 -0
  125. package/vendor/raylib/projects/VS2022/examples/shapes_bouncing_ball.vcxproj +387 -0
  126. package/vendor/raylib/projects/VS2022/examples/shapes_collision_area.vcxproj +387 -0
  127. package/vendor/raylib/projects/VS2022/examples/shapes_colors_palette.vcxproj +387 -0
  128. package/vendor/raylib/projects/VS2022/examples/shapes_draw_circle_sector.vcxproj +387 -0
  129. package/vendor/raylib/projects/VS2022/examples/shapes_draw_rectangle_rounded.vcxproj +387 -0
  130. package/vendor/raylib/projects/VS2022/examples/shapes_draw_ring.vcxproj +387 -0
  131. package/vendor/raylib/projects/VS2022/examples/shapes_easings_ball_anim.vcxproj +387 -0
  132. package/vendor/raylib/projects/VS2022/examples/shapes_easings_box_anim.vcxproj +387 -0
  133. package/vendor/raylib/projects/VS2022/examples/shapes_easings_rectangle_array.vcxproj +387 -0
  134. package/vendor/raylib/projects/VS2022/examples/shapes_following_eyes.vcxproj +387 -0
  135. package/vendor/raylib/projects/VS2022/examples/shapes_lines_bezier.vcxproj +387 -0
  136. package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib.vcxproj +387 -0
  137. package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib_anim.vcxproj +387 -0
  138. package/vendor/raylib/projects/VS2022/examples/shapes_rectangle_scaling.vcxproj +387 -0
  139. package/vendor/raylib/projects/VS2022/examples/text_codepoints_loading.vcxproj +387 -0
  140. package/vendor/raylib/projects/VS2022/examples/text_draw_3d.vcxproj +387 -0
  141. package/vendor/raylib/projects/VS2022/examples/text_font_filters.vcxproj +387 -0
  142. package/vendor/raylib/projects/VS2022/examples/text_font_loading.vcxproj +387 -0
  143. package/vendor/raylib/projects/VS2022/examples/text_font_sdf.vcxproj +387 -0
  144. package/vendor/raylib/projects/VS2022/examples/text_font_spritefont.vcxproj +387 -0
  145. package/vendor/raylib/projects/VS2022/examples/text_format_text.vcxproj +387 -0
  146. package/vendor/raylib/projects/VS2022/examples/text_input_box.vcxproj +387 -0
  147. package/vendor/raylib/projects/VS2022/examples/text_raylib_fonts.vcxproj +387 -0
  148. package/vendor/raylib/projects/VS2022/examples/text_rectangle_bounds.vcxproj +387 -0
  149. package/vendor/raylib/projects/VS2022/examples/text_unicode.vcxproj +387 -0
  150. package/vendor/raylib/projects/VS2022/examples/text_writing_anim.vcxproj +387 -0
  151. package/vendor/raylib/projects/VS2022/examples/textures_background_scrolling.vcxproj +387 -0
  152. package/vendor/raylib/projects/VS2022/examples/textures_blend_modes.vcxproj +387 -0
  153. package/vendor/raylib/projects/VS2022/examples/textures_bunnymark.vcxproj +387 -0
  154. package/vendor/raylib/projects/VS2022/examples/textures_draw_tiled.vcxproj +387 -0
  155. package/vendor/raylib/projects/VS2022/examples/textures_fog_of_war.vcxproj +387 -0
  156. package/vendor/raylib/projects/VS2022/examples/textures_gif_player.vcxproj +387 -0
  157. package/vendor/raylib/projects/VS2022/examples/textures_image_drawing.vcxproj +387 -0
  158. package/vendor/raylib/projects/VS2022/examples/textures_image_generation.vcxproj +387 -0
  159. package/vendor/raylib/projects/VS2022/examples/textures_image_loading.vcxproj +387 -0
  160. package/vendor/raylib/projects/VS2022/examples/textures_image_processing.vcxproj +387 -0
  161. package/vendor/raylib/projects/VS2022/examples/textures_image_text.vcxproj +387 -0
  162. package/vendor/raylib/projects/VS2022/examples/textures_logo_raylib.vcxproj +387 -0
  163. package/vendor/raylib/projects/VS2022/examples/textures_mouse_painting.vcxproj +387 -0
  164. package/vendor/raylib/projects/VS2022/examples/textures_npatch_drawing.vcxproj +387 -0
  165. package/vendor/raylib/projects/VS2022/examples/textures_particles_blending.vcxproj +387 -0
  166. package/vendor/raylib/projects/VS2022/examples/textures_polygon.vcxproj +387 -0
  167. package/vendor/raylib/projects/VS2022/examples/textures_raw_data.vcxproj +387 -0
  168. package/vendor/raylib/projects/VS2022/examples/textures_sprite_anim.vcxproj +387 -0
  169. package/vendor/raylib/projects/VS2022/examples/textures_sprite_button.vcxproj +387 -0
  170. package/vendor/raylib/projects/VS2022/examples/textures_sprite_explosion.vcxproj +387 -0
  171. package/vendor/raylib/projects/VS2022/examples/textures_srcrec_dstrec.vcxproj +387 -0
  172. package/vendor/raylib/projects/VS2022/examples/textures_to_image.vcxproj +387 -0
  173. package/vendor/raylib/projects/VS2022/raylib/raylib.vcxproj +340 -0
  174. package/vendor/raylib/projects/VS2022/raylib.sln +2347 -0
  175. package/build/qemu/2.1.0-beta.1/koffi_darwin_arm64.tar.gz +0 -0
  176. package/build/qemu/2.1.0-beta.1/koffi_darwin_x64.tar.gz +0 -0
  177. package/build/qemu/2.1.0-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
  178. package/build/qemu/2.1.0-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
  179. package/build/qemu/2.1.0-beta.1/koffi_freebsd_x64.tar.gz +0 -0
  180. package/build/qemu/2.1.0-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
  181. package/build/qemu/2.1.0-beta.1/koffi_linux_arm64.tar.gz +0 -0
  182. package/build/qemu/2.1.0-beta.1/koffi_linux_ia32.tar.gz +0 -0
  183. package/build/qemu/2.1.0-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  184. package/build/qemu/2.1.0-beta.1/koffi_linux_x64.tar.gz +0 -0
  185. package/build/qemu/2.1.0-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
  186. package/build/qemu/2.1.0-beta.1/koffi_openbsd_x64.tar.gz +0 -0
  187. package/build/qemu/2.1.0-beta.1/koffi_win32_arm64.tar.gz +0 -0
  188. package/build/qemu/2.1.0-beta.1/koffi_win32_ia32.tar.gz +0 -0
  189. package/build/qemu/2.1.0-beta.1/koffi_win32_x64.tar.gz +0 -0
  190. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  191. package/doc/dist/doctrees/changes.doctree +0 -0
  192. package/doc/dist/doctrees/contribute.doctree +0 -0
  193. package/doc/dist/doctrees/environment.pickle +0 -0
  194. package/doc/dist/doctrees/functions.doctree +0 -0
  195. package/doc/dist/doctrees/index.doctree +0 -0
  196. package/doc/dist/doctrees/memory.doctree +0 -0
  197. package/doc/dist/doctrees/platforms.doctree +0 -0
  198. package/doc/dist/doctrees/start.doctree +0 -0
  199. package/doc/dist/doctrees/types.doctree +0 -0
  200. package/doc/dist/html/.buildinfo +0 -4
  201. package/doc/dist/html/_sources/benchmarks.md.txt +0 -137
  202. package/doc/dist/html/_sources/changes.md.txt +0 -161
  203. package/doc/dist/html/_sources/contribute.md.txt +0 -127
  204. package/doc/dist/html/_sources/functions.md.txt +0 -355
  205. package/doc/dist/html/_sources/index.rst.txt +0 -39
  206. package/doc/dist/html/_sources/memory.md.txt +0 -32
  207. package/doc/dist/html/_sources/platforms.md.txt +0 -31
  208. package/doc/dist/html/_sources/start.md.txt +0 -100
  209. package/doc/dist/html/_sources/types.md.txt +0 -588
  210. package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +0 -134
  211. package/doc/dist/html/_static/basic.css +0 -932
  212. package/doc/dist/html/_static/bench_linux.png +0 -0
  213. package/doc/dist/html/_static/bench_windows.png +0 -0
  214. package/doc/dist/html/_static/custom.css +0 -22
  215. package/doc/dist/html/_static/debug.css +0 -69
  216. package/doc/dist/html/_static/doctools.js +0 -264
  217. package/doc/dist/html/_static/documentation_options.js +0 -14
  218. package/doc/dist/html/_static/file.png +0 -0
  219. package/doc/dist/html/_static/jquery-3.6.0.js +0 -10881
  220. package/doc/dist/html/_static/jquery.js +0 -2
  221. package/doc/dist/html/_static/language_data.js +0 -199
  222. package/doc/dist/html/_static/minus.png +0 -0
  223. package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
  224. package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
  225. package/doc/dist/html/_static/perf_linux_20220627.png +0 -0
  226. package/doc/dist/html/_static/perf_linux_20220628.png +0 -0
  227. package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
  228. package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
  229. package/doc/dist/html/_static/perf_windows_20220627.png +0 -0
  230. package/doc/dist/html/_static/perf_windows_20220628.png +0 -0
  231. package/doc/dist/html/_static/plus.png +0 -0
  232. package/doc/dist/html/_static/pygments.css +0 -252
  233. package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
  234. package/doc/dist/html/_static/scripts/furo.js +0 -3
  235. package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +0 -7
  236. package/doc/dist/html/_static/scripts/furo.js.map +0 -1
  237. package/doc/dist/html/_static/searchtools.js +0 -531
  238. package/doc/dist/html/_static/skeleton.css +0 -296
  239. package/doc/dist/html/_static/styles/furo-extensions.css +0 -2
  240. package/doc/dist/html/_static/styles/furo-extensions.css.map +0 -1
  241. package/doc/dist/html/_static/styles/furo.css +0 -2
  242. package/doc/dist/html/_static/styles/furo.css.map +0 -1
  243. package/doc/dist/html/_static/underscore-1.13.1.js +0 -2042
  244. package/doc/dist/html/_static/underscore.js +0 -6
  245. package/doc/dist/html/benchmarks.html +0 -572
  246. package/doc/dist/html/changes.html +0 -668
  247. package/doc/dist/html/contribute.html +0 -404
  248. package/doc/dist/html/functions.html +0 -657
  249. package/doc/dist/html/genindex.html +0 -254
  250. package/doc/dist/html/index.html +0 -360
  251. package/doc/dist/html/memory.html +0 -347
  252. package/doc/dist/html/objects.inv +0 -0
  253. package/doc/dist/html/platforms.html +0 -372
  254. package/doc/dist/html/search.html +0 -262
  255. package/doc/dist/html/searchindex.js +0 -1
  256. package/doc/dist/html/start.html +0 -385
  257. package/doc/dist/html/types.html +0 -1097
package/CMakeLists.txt CHANGED
@@ -31,7 +31,7 @@ if(MSVC)
31
31
  enable_language(ASM_MASM)
32
32
  endif()
33
33
  else()
34
- add_compile_options(-Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter)
34
+ add_compile_options(-Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wswitch -Werror=switch)
35
35
  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
36
36
  add_compile_options(-Wno-unknown-warning-option)
37
37
  endif()
package/ChangeLog.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  ## History
4
4
 
5
+ ### Koffi 2.1.0
6
+
7
+ **Main changes:**
8
+
9
+ - Add [koffi.as()](functions.md#polymorphic-parameters) to support polymorphic APIs based on `void *` parameters
10
+ - Add [endian-sensitive integer types](types.md#endian-sensitive-types): `intX_le_t`, `intX_be_t`
11
+ - Accept typed arrays for `void *` parameters
12
+ - Introduce `koffi.opaque()` to replace `koffi.handle()` (which remains supported until Koffi 3.0)
13
+ - Support JS Array and TypedArray to fill struct and array pointer members
14
+
15
+ **Other changes:**
16
+
17
+ - Improve global performance with inlining and unity builds
18
+ - Add `size_t` primitive type
19
+ - Support member-specific alignement values in structs
20
+ - Detect impossible parameter and return types (such as non-pointer opaque types)
21
+ - Various documentation fixes and improvements
22
+
5
23
  ### Koffi 2.0.1
6
24
 
7
25
  **Main changes:**
package/doc/Makefile CHANGED
@@ -6,7 +6,7 @@
6
6
  SPHINXOPTS ?=
7
7
  SPHINXBUILD ?= sphinx-build
8
8
  SOURCEDIR = .
9
- BUILDDIR = dist
9
+ BUILDDIR = ../build/doc
10
10
 
11
11
  # Put it first so that "make" without argument is like "make help".
12
12
  help:
package/doc/benchmarks.md CHANGED
@@ -10,8 +10,8 @@ Here is a quick overview of the execution time of Koffi calls on three benchmark
10
10
 
11
11
  <table style="margin: 0 auto;">
12
12
  <tr>
13
- <td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
- <td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
13
+ <td><a href="_static/perf_linux_20220812.png" target="_blank"><img src="_static/perf_linux_20220812.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
14
+ <td><a href="_static/perf_windows_20220812.png" target="_blank"><img src="_static/perf_windows_20220812.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
15
15
  </tr>
16
16
  </table>
17
17
 
@@ -31,9 +31,9 @@ This test is based around repeated calls to a simple standard C function atoi, a
31
31
 
32
32
  Benchmark | Iteration time | Relative performance | Overhead
33
33
  ------------- | -------------- | -------------------- | --------
34
- rand_napi | 644 ns | x1.00 | (ref)
35
- rand_koffi | 950 ns | x0.68 | +48%
36
- rand_node_ffi | 30350 ns | x0.02 | +4613%
34
+ rand_napi | 842 ns | x1.00 | (ref)
35
+ rand_koffi | 1114 ns | x0.76 | +32%
36
+ rand_node_ffi | 44845 ns | x0.02 | +5224%
37
37
 
38
38
  Because rand is a pretty small function, the FFI overhead is clearly visible.
39
39
 
@@ -43,9 +43,9 @@ This test is similar to the rand one, but it is based on atoi, which takes a str
43
43
 
44
44
  Benchmark | Iteration time | Relative performance | Overhead
45
45
  ------------- | -------------- | -------------------- | --------
46
- atoi_napi | 1104 ns | x1.00 | (ref)
47
- atoi_koffi | 1778 ns | x0.62 | +61%
48
- atoi_node_ffi | 125300 ns | x0.009 | +11250%
46
+ atoi_napi | 921 ns | x1.00 | (ref)
47
+ atoi_koffi | 1357 ns | x0.68 | +47%
48
+ atoi_node_ffi | 152550 ns | x0.006 | +16472%
49
49
 
50
50
  Because atoi is a pretty small function, the FFI overhead is clearly visible.
51
51
 
@@ -77,9 +77,9 @@ This test is based around repeated calls to a simple standard C function atoi, a
77
77
 
78
78
  Benchmark | Iteration time | Relative performance | Overhead
79
79
  ------------- | -------------- | -------------------- | --------
80
- rand_napi | 965 ns | x1.00 | (ref)
81
- rand_koffi | 1248 ns | x0.77 | +29%
82
- rand_node_ffi | 41500 ns | x0.02 | +4203%
80
+ rand_napi | 964 ns | x1.00 | (ref)
81
+ rand_koffi | 1274 ns | x0.76 | +32%
82
+ rand_node_ffi | 42300 ns | x0.02 | +4289%
83
83
 
84
84
  Because rand is a pretty small function, the FFI overhead is clearly visible.
85
85
 
@@ -91,9 +91,9 @@ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5
91
91
 
92
92
  Benchmark | Iteration time | Relative performance | Overhead
93
93
  ------------- | -------------- | -------------------- | --------
94
- atoi_napi | 1393 ns | x1.00 | (ref)
95
- atoi_koffi | 2246 ns | x0.62 | +61%
96
- atoi_node_ffi | 157550 ns | x0.009 | +11210%
94
+ atoi_napi | 1415 ns | x1.00 | (ref)
95
+ atoi_koffi | 2193 ns | x0.65 | +55%
96
+ atoi_node_ffi | 168300 ns | x0.008 | +11792%
97
97
 
98
98
  Because atoi is a pretty small function, the FFI overhead is clearly visible.
99
99
 
Binary file
package/doc/conf.py CHANGED
@@ -12,6 +12,7 @@ with open(os.path.dirname(__file__) + '/../package.json') as f:
12
12
 
13
13
  version = config['version']
14
14
  revision = config['version']
15
+ stable = config['stable']
15
16
 
16
17
  # -- General configuration ---------------------------------------------------
17
18
 
@@ -61,6 +62,10 @@ html_sidebars = {
61
62
  ]
62
63
  }
63
64
 
65
+ html_context = {
66
+ "stable": stable
67
+ }
68
+
64
69
  # -- MyST parser options -------------------------------------------------
65
70
 
66
71
  myst_enable_extensions = [
package/doc/functions.md CHANGED
@@ -105,7 +105,7 @@ printf('Integer %d, double %g, str %s', 'int', 6, 'double', 8.5, 'str', 'THE END
105
105
 
106
106
  On x86 platforms, only the Cdecl convention can be used for variadic functions.
107
107
 
108
- ## C to JS conversion gotchas
108
+ ## Special considerations
109
109
 
110
110
  ### Output parameters
111
111
 
@@ -177,8 +177,72 @@ let db = out[0];
177
177
  sqlite3_close_v2(db);
178
178
  ```
179
179
 
180
+ ### Polymorphic parameters
181
+
182
+ *New in Koffi 2.1*
183
+
184
+ Many C functions use `void *` 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.
185
+
186
+ Koffi provides two features to deal with this:
187
+
188
+ - Typed JS arrays can be used as values in place everywhere `void *` is expected. See [dynamic arrays](types.md#array-pointers-dynamic-arrays) for more information, for input or output.
189
+ - You can use `koffi.as(value, type)` to tell Koffi what kind of type is actually expected.
190
+
191
+ The example below shows the use of `koffi.as()` to read the header of a PNG file with `fread()`.
192
+
193
+ ```js
194
+ const koffi = require('koffi');
195
+ const lib = koffi.load('libc.so.6');
196
+
197
+ const FILE = koffi.opaque('FILE');
198
+
199
+ const PngHeader = koffi.pack('PngHeader', {
200
+ signature: koffi.array('uint8_t', 8),
201
+ ihdr: koffi.pack({
202
+ length: 'uint32_be_t',
203
+ chunk: koffi.array('char', 4),
204
+ width: 'uint32_be_t',
205
+ height: 'uint32_be_t',
206
+ depth: 'uint8_t',
207
+ color: 'uint8_t',
208
+ compression: 'uint8_t',
209
+ filter: 'uint8_t',
210
+ interlace: 'uint8_t',
211
+ crc: 'uint32_be_t'
212
+ })
213
+ });
214
+
215
+ const fopen = lib.func('FILE *fopen(const char *path, const char *mode)');
216
+ const fclose = lib.func('int fclose(FILE *fp)');
217
+ const fread = lib.func('size_t fread(_Out_ void *ptr, size_t size, size_t nmemb, FILE *fp)');
218
+
219
+ let filename = process.argv[2];
220
+ if (filename == null)
221
+ throw new Error('Usage: node png.js <image.png>');
222
+
223
+ let hdr = {};
224
+ {
225
+
226
+ let fp = fopen(filename, 'rb');
227
+ if (!fp)
228
+ throw new Error(`Failed to open '${filename}'`);
229
+
230
+ try {
231
+ let len = fread(koffi.as(hdr, 'PngHeader *'), 1, koffi.sizeof(PngHeader), fp);
232
+ if (len < koffi.sizeof(PngHeader))
233
+ throw new Error('Failed to read PNG header');
234
+ } finally {
235
+ fclose(fp);
236
+ }
237
+ }
238
+
239
+ console.log('PNG header:', hdr);
240
+ ```
241
+
180
242
  ### Heap-allocated values
181
243
 
244
+ *New in Koffi 2.0*
245
+
182
246
  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.
183
247
 
184
248
  For opaque types, such as FILE, this does not matter because you will explicitly call `fclose()` 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.
@@ -299,6 +363,8 @@ console.log(ret);
299
363
 
300
364
  ### Registered callbacks
301
365
 
366
+ *New in Koffi 2.0*
367
+
302
368
  Use registered callbacks when the function needs to be called at a later time (e.g. log handler, event handler, `fopencookie/funopen`). Call `koffi.register(func, type)` to register a callback function, with two arguments: the JS function, and the callback type.
303
369
 
304
370
  When you are done, call `koffi.unregister()` (with the value returned by `koffi.register()`) 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.
package/doc/index.rst CHANGED
@@ -1,5 +1,5 @@
1
- Koffi |version|
2
- ===============
1
+ Koffi
2
+ =====
3
3
 
4
4
  Overview
5
5
  --------
package/doc/make.bat CHANGED
@@ -8,7 +8,7 @@ if "%SPHINXBUILD%" == "" (
8
8
  set SPHINXBUILD=sphinx-build
9
9
  )
10
10
  set SOURCEDIR=.
11
- set BUILDDIR=dist
11
+ set BUILDDIR=../build/doc
12
12
 
13
13
  %SPHINXBUILD% >NUL 2>NUL
14
14
  if errorlevel 9009 (
@@ -1,5 +1,4 @@
1
1
  <div style="text-align: center; margin-top: 2em;">
2
- <a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-{{version}}-brightgreen" alt="NPM"/></a>
2
+ <a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-{{ stable }}-brightgreen" alt="NPM"/></a>
3
3
  <a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
4
4
  </div>
5
-
package/doc/types.md CHANGED
@@ -2,45 +2,34 @@
2
2
 
3
3
  ## Primitive types
4
4
 
5
+ ### Standard types
6
+
5
7
  While the C standard allows for variation in the size of most integer types, Koffi enforces the same definition for most primitive types, listed below:
6
8
 
7
- JS type | C type | Bytes | Signedness | Note
8
- ----------------- | ------------------ | ----- | ---------- | ---------------------------
9
- Undefined | void | 0 | | Only valid as a return type
10
- Number (integer) | int8 | 1 | Signed |
11
- Number (integer) | int8_t | 1 | Signed |
12
- Number (integer) | uint8 | 1 | Unsigned |
13
- Number (integer) | uint8_t | 1 | Unsigned |
14
- Number (integer) | char | 1 | Signed |
15
- Number (integer) | uchar | 1 | Unsigned |
16
- Number (integer) | unsigned char | 1 | Unsigned |
17
- Number (integer) | char16 | 2 | Signed |
18
- Number (integer) | char16_t | 2 | Signed |
19
- Number (integer) | int16 | 2 | Signed |
20
- Number (integer) | int16_t | 2 | Signed |
21
- Number (integer) | uint16 | 2 | Unsigned |
22
- Number (integer) | uint16_t | 2 | Unsigned |
23
- Number (integer) | short | 2 | Signed |
24
- Number (integer) | unsigned short | 2 | Unsigned |
25
- Number (integer) | int32 | 4 | Signed |
26
- Number (integer) | int32_t | 4 | Signed |
27
- Number (integer) | uint32 | 4 | Unsigned |
28
- Number (integer) | uint32_t | 4 | Unsigned |
29
- Number (integer) | int | 4 | Signed |
30
- Number (integer) | uint | 4 | Unsigned |
31
- Number (integer) | unsigned int | 4 | Unsigned |
32
- Number (integer) | int64 | 8 | Signed |
33
- Number (integer) | int64_t | 8 | Signed |
34
- Number (integer) | uint64 | 8 | Unsigned |
35
- Number (integer) | uint64_t | 8 | Unsigned |
36
- Number (integer) | longlong | 8 | Signed |
37
- Number (integer) | long long | 8 | Signed |
38
- Number (integer) | ulonglong | 8 | Unsigned |
39
- Number (integer) | unsigned long long | 8 | Unsigned |
40
- Number (float) | float32 | 4 | |
41
- Number (float) | float64 | 8 | |
42
- Number (float) | float | 4 | |
43
- Number (float) | double | 8 | |
9
+ JS type | C type | Bytes | Signedness | Note
10
+ ---------------- | ----------------------------- | ----- | ---------- | ---------------------------
11
+ Undefined | void | 0 | | Only valid as a return type
12
+ Number (integer) | int8, int8_t | 1 | Signed |
13
+ Number (integer) | uint8, uint8_t | 1 | Unsigned |
14
+ Number (integer) | char | 1 | Signed |
15
+ Number (integer) | uchar, unsigned char | 1 | Unsigned |
16
+ Number (integer) | char16, char16_t | 2 | Signed |
17
+ Number (integer) | int16, int16_t | 2 | Signed |
18
+ Number (integer) | uint16, uint16_t | 2 | Unsigned |
19
+ Number (integer) | short | 2 | Signed |
20
+ Number (integer) | ushort, unsigned short | 2 | Unsigned |
21
+ Number (integer) | int32, int32_t | 4 | Signed |
22
+ Number (integer) | uint32, uint32_t | 4 | Unsigned |
23
+ Number (integer) | int | 4 | Signed |
24
+ Number (integer) | uint, unsigned int | 4 | Unsigned |
25
+ Number (integer) | int64, int64_t | 8 | Signed |
26
+ Number (integer) | uint64, uint64_t | 8 | Unsigned |
27
+ Number (integer) | longlong, long long | 8 | Signed |
28
+ Number (integer) | ulonglong, unsigned long long | 8 | Unsigned |
29
+ Number (float) | float32 | 4 | |
30
+ Number (float) | float64 | 8 | |
31
+ Number (float) | float | 4 | |
32
+ Number (float) | double | 8 | |
44
33
 
45
34
  Koffi also accepts BigInt values when converting from JS to C integers. If the value exceeds the range of the C type, Koffi will convert the number to an undefined value. In the reverse direction, BigInt values are automatically used when needed for big 64-bit integers.
46
35
 
@@ -56,8 +45,8 @@ Number (integer) | intptr | Signed | 4 or 8 bytes depending on reg
56
45
  Number (integer) | intptr_t | Signed | 4 or 8 bytes depending on register width
57
46
  Number (integer) | uintptr | Unsigned | 4 or 8 bytes depending on register width
58
47
  Number (integer) | uintptr_t | Unsigned | 4 or 8 bytes depending on register width
59
- String | str (string) | | JS strings are converted to and from UTF-8
60
- String | str16 (string16) | | JS strings are converted to and from UTF-16 (LE)
48
+ String | str, string | | JS strings are converted to and from UTF-8
49
+ String | str16, string16 | | JS strings are converted to and from UTF-16 (LE)
61
50
 
62
51
  Primitive types can be specified by name (in a string) or through `koffi.types`:
63
52
 
@@ -67,6 +56,27 @@ let struct1 = koffi.struct({ dummy: 'long' });
67
56
  let struct2 = koffi.struct({ dummy: koffi.types.long });
68
57
  ```
69
58
 
59
+ ### Endian-sensitive types
60
+
61
+ *New in Koffi 2.1*
62
+
63
+ Koffi defines a bunch of endian-sensitive types, which can be used when dealing with binary data (network payloads, binary file formats, etc.).
64
+
65
+ JS type | C type | Bytes | Signedness | Endianness
66
+ ---------------- | ---------------------- | ----- | ---------- | -------------
67
+ Number (integer) | int16_le, int16_le_t | 2 | Signed | Little Endian
68
+ Number (integer) | int16_be, int16_be_t | 2 | Signed | Big Endian
69
+ Number (integer) | uint16_le, uint16_le_t | 2 | Unsigned | Little Endian
70
+ Number (integer) | uint16_be, uint16_be_t | 2 | Unsigned | Big Endian
71
+ Number (integer) | int32_le, int32_le_t | 4 | Signed | Little Endian
72
+ Number (integer) | int32_be, int32_be_t | 4 | Signed | Big Endian
73
+ Number (integer) | uint32_le, uint32_le_t | 4 | Unsigned | Little Endian
74
+ Number (integer) | uint32_be, uint32_be_t | 4 | Unsigned | Big Endian
75
+ Number (integer) | int64_le, int64_le_t | 8 | Signed | Little Endian
76
+ Number (integer) | int64_be, int64_be_t | 8 | Signed | Big Endian
77
+ Number (integer) | uint64_le, uint64_le_t | 8 | Unsigned | Little Endian
78
+ Number (integer) | uint64_be, uint64_be_t | 8 | Unsigned | Big Endian
79
+
70
80
  ## Struct types
71
81
 
72
82
  ### Struct definition
@@ -101,16 +111,6 @@ const A = koffi.struct('A', {
101
111
  });
102
112
  ```
103
113
 
104
- Koffi follows the C and ABI rules regarding struct alignment and padding.
105
-
106
- Once a struct is declared, you can use it by name (with a string, like you can do for primitive types) or through the value returned by the call to `koffi.struct()`. Only the latter is possible when declaring an anonymous struct.
107
-
108
- ```js
109
- // The following two function declarations are equivalent, and declare a function taking an A value and returning A
110
- const Function1 = lib.func('A Function(A value)');
111
- const Function2 = lib.func('Function', A, [A]);
112
- ```
113
-
114
114
  Koffi automatically follows the platform C ABI regarding alignment and padding. However, you can override these rules if needed with:
115
115
 
116
116
  - Pack all members without padding with `koffi.pack()` (instead of `koffi.struct()`)
@@ -123,13 +123,21 @@ const PackedStruct = koffi.pack('PackedStruct', {
123
123
  b: 'int16_t'
124
124
  });
125
125
 
126
- // This one is 18 bytes long, the second member has an alignment requirement of 16 bytes
126
+ // This one is 10 bytes long, the second member has an alignment requirement of 8 bytes
127
127
  const BigStruct = koffi.struct('BigStruct', {
128
128
  a: 'int8_t',
129
- b: [16, 'int16_t']
129
+ b: [8, 'int16_t']
130
130
  })
131
131
  ```
132
132
 
133
+ Once a struct is declared, you can use it by name (with a string, like you can do for primitive types) or through the value returned by the call to `koffi.struct()`. Only the latter is possible when declaring an anonymous struct.
134
+
135
+ ```js
136
+ // The following two function declarations are equivalent, and declare a function taking an A value and returning A
137
+ const Function1 = lib.func('A Function(A value)');
138
+ const Function2 = lib.func('Function', A, [A]);
139
+ ```
140
+
133
141
  ### Opaque types
134
142
 
135
143
  Many C libraries use some kind of object-oriented API, with a pair of functions dedicated to create and delete objects. An obvious example of this can be found in stdio.h, with the opaque `FILE *` pointer. You can open and close files with `fopen()` and `fclose()`, and manipule the opaque pointer with other functions such as `fread()` or `ftell()`.
@@ -328,8 +336,8 @@ In C, pointer arguments are used for differenty purposes. It is important to dis
328
336
 
329
337
  - **Struct pointers**: Use of struct pointers by C libraries fall in two cases: avoid (potentially) expensive copies, and to let the function change struct contents (output or input/output arguments).
330
338
  - **Opaque pointers**: the library does not expose the contents of the structs, and only provides you with a pointer to it (e.g. `FILE *`). Only the functions provided by the library can do something with this pointer, in Koffi we call this an opaque type. This is usually done for ABI-stability reason, and to prevent library users from messing directly with library internals.
331
- - **Arrays**: in C, you dynamically-sized arrays are usually passed to functions with pointers, either NULL-terminated (or any other sentinel value) or with an additional length argument.
332
339
  - **Pointers to primitive types**: This is more rare, and generally used for output or input/output arguments. The Win32 API has a lot of these.
340
+ - **Arrays**: in C, you dynamically-sized arrays are usually passed to functions with pointers, either NULL-terminated (or any other sentinel value) or with an additional length argument.
333
341
 
334
342
  ### Struct pointers
335
343
 
@@ -357,6 +365,8 @@ console.log(pos);
357
365
 
358
366
  ### Named pointer types
359
367
 
368
+ *New in Koffi 2.0*
369
+
360
370
  Some C libraries use handles, which behave as pointers to opaque structs. An example of this is the HANDLE type in the Win32 API. If you want to reproduce this behavior, you can define a **named pointer type** to an opaque type, like so:
361
371
 
362
372
  ```js
@@ -367,111 +377,6 @@ const GetHandleInformation = lib.func('bool __stdcall GetHandleInformation(HANDL
367
377
  const CloseHandle = lib.func('bool __stdcall CloseHandle(HANDLE h)');
368
378
  ```
369
379
 
370
- ### Array pointers
371
-
372
- In C, dynamically-sized arrays are usually passed around as pointers. The length is either passed as an additional argument, or inferred from the array content itself, for example with a terminating sentinel value (such as a NULL pointers in the case of an array of strings).
373
-
374
- Koffi can translate JS arrays and TypedArrays to pointer arguments. However, because C does not have a proper notion of dynamically-sized arrays (fat pointers), you need to provide the length or the sentinel value yourself depending on the API.
375
-
376
- Here is a simple example of a C function taking a NULL-terminated list of strings as input, to calculate the total length of all strings.
377
-
378
- ```c
379
- // Build with: clang -fPIC -o length.so -shared length.c -Wall -O2
380
-
381
- #include <stdlib.h>
382
- #include <stdint.h>
383
- #include <string.h>
384
-
385
- int64_t ComputeTotalLength(const char **strings)
386
- {
387
- int64_t total = 0;
388
-
389
- for (const char **ptr = strings; *ptr; ptr++) {
390
- const char *str = *ptr;
391
- total += strlen(str);
392
- }
393
-
394
- return total;
395
- }
396
- ```
397
-
398
- ```js
399
- const koffi = require('koffi');
400
- const lib = koffi.load('./length.so');
401
-
402
- const ComputeTotalLength = lib.func('int64_t ComputeTotalLength(const char **strings)');
403
-
404
- let strings = ['Get', 'Total', 'Length', null];
405
- let total = ComputeTotalLength(strings);
406
-
407
- console.log(total); // Prints 14
408
- ```
409
-
410
- By default, just like for objects, array arguments are copied from JS to C but not vice-versa. You can however change the direction as documented in the section on [output parameters](functions.md#output-parameters).
411
-
412
- Here is an example based on the Win32 API, listing files in the current directory with `FindFirstFileW()` and `FindNextFileW()`:
413
-
414
- ```js
415
- const koffi = require('koffi');
416
- const lib = koffi.load('kernel32.dll');
417
-
418
- const HANDLE = koffi.pointer('HANDLE', koffi.opaque());
419
- const FILETIME = koffi.struct('FILETIME', {
420
- dwLowDateTime: 'uint',
421
- dwHighDateTime: 'uint'
422
- });
423
- const WIN32_FIND_DATA = koffi.struct('WIN32_FIND_DATA', {
424
- dwFileAttributes: 'uint',
425
- ftCreationTime: FILETIME,
426
- ftLastAccessTime: FILETIME,
427
- ftLastWriteTime: FILETIME,
428
- nFileSizeHigh: 'uint',
429
- nFileSizeLow: 'uint',
430
- dwReserved0: 'uint',
431
- dwReserved1: 'uint',
432
- cFileName: koffi.array('char16', 260),
433
- cAlternateFileName: koffi.array('char16', 14),
434
- dwFileType: 'uint', // Obsolete. Do not use.
435
- dwCreatorType: 'uint', // Obsolete. Do not use
436
- wFinderFlags: 'ushort' // Obsolete. Do not use
437
- });
438
-
439
- const FindFirstFile = lib.func('HANDLE __stdcall FindFirstFileW(str16 path, _Out_ WIN32_FIND_DATA *data)');
440
- const FindNextFile = lib.func('bool __stdcall FindNextFileW(HANDLE h, _Out_ WIN32_FIND_DATA *data)');
441
- const FindClose = lib.func('bool __stdcall FindClose(HANDLE h)');
442
- const GetLastError = lib.func('uint GetLastError()');
443
-
444
- function list(dirname) {
445
- let filenames = [];
446
-
447
- let data = {};
448
- let h = FindFirstFile(dirname + '\\*', data);
449
-
450
- if (!h) {
451
- if (GetLastError() == 2) // ERROR_FILE_NOT_FOUND
452
- return filenames;
453
- throw new Error('FindFirstFile() failed');
454
- }
455
-
456
- try {
457
- do {
458
- if (data.cFileName != '.' && data.cFileName != '..')
459
- filenames.push(data.cFileName);
460
- } while (FindNextFile(h, data));
461
-
462
- if (GetLastError() != 18) // ERROR_NO_MORE_FILES
463
- throw new Error('FindNextFile() failed');
464
- } finally {
465
- FindClose(h);
466
- }
467
-
468
- return filenames;
469
- }
470
-
471
- let filenames = list('.');
472
- console.log(filenames);
473
- ```
474
-
475
380
  ### Pointers to primitive types
476
381
 
477
382
  In javascript, it is not possible to pass a primitive value by reference to another function. This means that you cannot call a function and expect it to modify the value of one of its number or string parameter.
@@ -509,7 +414,9 @@ AddInt(sum, 6);
509
414
  console.log(sum[0]); // Prints 42
510
415
  ```
511
416
 
512
- ## Fixed-size C arrays
417
+ ## Array types
418
+
419
+ ### Fixed-size C arrays
513
420
 
514
421
  Fixed-size arrays are declared with `koffi.array(type, length)`. Just like in C, they cannot be passed as functions parameters (they degenerate to pointers), or returned by value. You can however embed them in struct types.
515
422
 
@@ -541,7 +448,7 @@ console.log(ReturnFoo1({ i: 5, a16: [6, 8] })) // Prints { i: 5, a16: Int16Array
541
448
  console.log(ReturnFoo2({ i: 5, a16: [6, 8] })) // Prints { i: 5, a16: [6, 8] }
542
449
  ```
543
450
 
544
- ### Handling of strings
451
+ ### Fixed-size string buffers
545
452
 
546
453
  Koffi can also convert JS strings to fixed-sized arrays in the following cases:
547
454
 
@@ -550,6 +457,48 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
550
457
 
551
458
  The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `string` array hint (e.g. `koffi.array('char', 8, 'string')`).
552
459
 
460
+ ### Array pointers (dynamic arrays)
461
+
462
+ In C, dynamically-sized arrays are usually passed around as pointers. The length is either passed as an additional argument, or inferred from the array content itself, for example with a terminating sentinel value (such as a NULL pointers in the case of an array of strings).
463
+
464
+ Koffi can translate JS arrays and TypedArrays to pointer arguments. However, because C does not have a proper notion of dynamically-sized arrays (fat pointers), you need to provide the length or the sentinel value yourself depending on the API.
465
+
466
+ Here is a simple example of a C function taking a NULL-terminated list of strings as input, to calculate the total length of all strings.
467
+
468
+ ```c
469
+ // Build with: clang -fPIC -o length.so -shared length.c -Wall -O2
470
+
471
+ #include <stdlib.h>
472
+ #include <stdint.h>
473
+ #include <string.h>
474
+
475
+ int64_t ComputeTotalLength(const char **strings)
476
+ {
477
+ int64_t total = 0;
478
+
479
+ for (const char **ptr = strings; *ptr; ptr++) {
480
+ const char *str = *ptr;
481
+ total += strlen(str);
482
+ }
483
+
484
+ return total;
485
+ }
486
+ ```
487
+
488
+ ```js
489
+ const koffi = require('koffi');
490
+ const lib = koffi.load('./length.so');
491
+
492
+ const ComputeTotalLength = lib.func('int64_t ComputeTotalLength(const char **strings)');
493
+
494
+ let strings = ['Get', 'Total', 'Length', null];
495
+ let total = ComputeTotalLength(strings);
496
+
497
+ console.log(total); // Prints 14
498
+ ```
499
+
500
+ By default, just like for objects, array arguments are copied from JS to C but not vice-versa. You can however change the direction as documented in the section on [output parameters](functions.md#output-parameters).
501
+
553
502
  ## Disposable types
554
503
 
555
504
  Disposable types allow you to register a function that will automatically called after each C to JS conversion performed by Koffi. This can be used to avoid leaking heap-allocated strings, for example.
@@ -560,6 +509,8 @@ Read the documentation for [disposable types](functions.md#heap-allocated-values
560
509
 
561
510
  ### Type introspection
562
511
 
512
+ *New in Koffi 2.0: `koffi.resolve()`*
513
+
563
514
  Koffi exposes three functions to explore type information:
564
515
 
565
516
  - `koffi.sizeof(type)` to get the size of a type
@@ -585,4 +536,6 @@ console.log(koffi.sizeof(koffi.types.long));
585
536
 
586
537
  ### Type aliases
587
538
 
539
+ *New in Koffi 2.0*
540
+
588
541
  You can alias a type with `koffi.alias(name, type)`. Aliased types are completely equivalent.