koffi 0.9.45 → 1.0.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 (147) hide show
  1. package/CMakeLists.txt +1 -1
  2. package/README.md +173 -113
  3. package/build/qemu/1.0.0/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/1.0.0/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/1.0.0/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/1.0.0/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/1.0.0/koffi_linux_arm.tar.gz +0 -0
  8. package/build/qemu/1.0.0/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/1.0.0/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/1.0.0/koffi_linux_x64.tar.gz +0 -0
  11. package/build/qemu/1.0.0/koffi_win32_ia32.tar.gz +0 -0
  12. package/build/qemu/1.0.0/koffi_win32_x64.tar.gz +0 -0
  13. package/package.json +3 -3
  14. package/src/call_arm32.cc +0 -9
  15. package/src/call_arm64.cc +17 -0
  16. package/qemu/build/0.9.45/koffi_freebsd_arm64.tar.gz +0 -0
  17. package/qemu/build/0.9.45/koffi_freebsd_ia32.tar.gz +0 -0
  18. package/qemu/build/0.9.45/koffi_freebsd_x64.tar.gz +0 -0
  19. package/qemu/build/0.9.45/koffi_linux_arm.tar.gz +0 -0
  20. package/qemu/build/0.9.45/koffi_linux_arm64.tar.gz +0 -0
  21. package/qemu/build/0.9.45/koffi_linux_ia32.tar.gz +0 -0
  22. package/qemu/build/0.9.45/koffi_linux_x64.tar.gz +0 -0
  23. package/qemu/build/0.9.45/koffi_win32_ia32.tar.gz +0 -0
  24. package/qemu/build/0.9.45/koffi_win32_x64.tar.gz +0 -0
  25. package/vendor/raylib/projects/VS2019/examples/audio_module_playing.vcxproj +0 -387
  26. package/vendor/raylib/projects/VS2019/examples/audio_multichannel_sound.vcxproj +0 -387
  27. package/vendor/raylib/projects/VS2019/examples/audio_music_stream.vcxproj +0 -387
  28. package/vendor/raylib/projects/VS2019/examples/audio_raw_stream.vcxproj +0 -387
  29. package/vendor/raylib/projects/VS2019/examples/audio_sound_loading.vcxproj +0 -387
  30. package/vendor/raylib/projects/VS2019/examples/core_2d_camera.vcxproj +0 -387
  31. package/vendor/raylib/projects/VS2019/examples/core_2d_camera_platformer.vcxproj +0 -387
  32. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_first_person.vcxproj +0 -387
  33. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_free.vcxproj +0 -387
  34. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_mode.vcxproj +0 -387
  35. package/vendor/raylib/projects/VS2019/examples/core_3d_picking.vcxproj +0 -387
  36. package/vendor/raylib/projects/VS2019/examples/core_basic_window.vcxproj +0 -387
  37. package/vendor/raylib/projects/VS2019/examples/core_custom_logging.vcxproj +0 -387
  38. package/vendor/raylib/projects/VS2019/examples/core_drop_files.vcxproj +0 -387
  39. package/vendor/raylib/projects/VS2019/examples/core_input_gamepad.vcxproj +0 -387
  40. package/vendor/raylib/projects/VS2019/examples/core_input_gestures.vcxproj +0 -387
  41. package/vendor/raylib/projects/VS2019/examples/core_input_keys.vcxproj +0 -387
  42. package/vendor/raylib/projects/VS2019/examples/core_input_mouse.vcxproj +0 -387
  43. package/vendor/raylib/projects/VS2019/examples/core_input_mouse_wheel.vcxproj +0 -387
  44. package/vendor/raylib/projects/VS2019/examples/core_input_multitouch.vcxproj +0 -387
  45. package/vendor/raylib/projects/VS2019/examples/core_loading_thread.vcxproj +0 -387
  46. package/vendor/raylib/projects/VS2019/examples/core_quat_conversion.vcxproj +0 -387
  47. package/vendor/raylib/projects/VS2019/examples/core_random_values.vcxproj +0 -387
  48. package/vendor/raylib/projects/VS2019/examples/core_scissor_test.vcxproj +0 -387
  49. package/vendor/raylib/projects/VS2019/examples/core_split_screen.vcxproj +0 -387
  50. package/vendor/raylib/projects/VS2019/examples/core_storage_values.vcxproj +0 -387
  51. package/vendor/raylib/projects/VS2019/examples/core_vr_simulator.vcxproj +0 -387
  52. package/vendor/raylib/projects/VS2019/examples/core_window_flags.vcxproj +0 -387
  53. package/vendor/raylib/projects/VS2019/examples/core_window_letterbox.vcxproj +0 -387
  54. package/vendor/raylib/projects/VS2019/examples/core_world_screen.vcxproj +0 -387
  55. package/vendor/raylib/projects/VS2019/examples/easings_testbed.vcxproj +0 -387
  56. package/vendor/raylib/projects/VS2019/examples/embedded_files_loading.vcxproj +0 -387
  57. package/vendor/raylib/projects/VS2019/examples/models_animation.vcxproj +0 -387
  58. package/vendor/raylib/projects/VS2019/examples/models_billboard.vcxproj +0 -387
  59. package/vendor/raylib/projects/VS2019/examples/models_box_collisions.vcxproj +0 -387
  60. package/vendor/raylib/projects/VS2019/examples/models_cubicmap.vcxproj +0 -387
  61. package/vendor/raylib/projects/VS2019/examples/models_first_person_maze.vcxproj +0 -387
  62. package/vendor/raylib/projects/VS2019/examples/models_geometric_shapes.vcxproj +0 -387
  63. package/vendor/raylib/projects/VS2019/examples/models_heightmap.vcxproj +0 -387
  64. package/vendor/raylib/projects/VS2019/examples/models_loading.vcxproj +0 -387
  65. package/vendor/raylib/projects/VS2019/examples/models_loading_gltf.vcxproj +0 -387
  66. package/vendor/raylib/projects/VS2019/examples/models_loading_vox.vcxproj +0 -387
  67. package/vendor/raylib/projects/VS2019/examples/models_mesh_generation.vcxproj +0 -387
  68. package/vendor/raylib/projects/VS2019/examples/models_mesh_picking.vcxproj +0 -387
  69. package/vendor/raylib/projects/VS2019/examples/models_orthographic_projection.vcxproj +0 -387
  70. package/vendor/raylib/projects/VS2019/examples/models_rlgl_solar_system.vcxproj +0 -387
  71. package/vendor/raylib/projects/VS2019/examples/models_skybox.vcxproj +0 -387
  72. package/vendor/raylib/projects/VS2019/examples/models_waving_cubes.vcxproj +0 -387
  73. package/vendor/raylib/projects/VS2019/examples/models_yaw_pitch_roll.vcxproj +0 -387
  74. package/vendor/raylib/projects/VS2019/examples/physics_demo.vcxproj +0 -387
  75. package/vendor/raylib/projects/VS2019/examples/physics_friction.vcxproj +0 -387
  76. package/vendor/raylib/projects/VS2019/examples/physics_movement.vcxproj +0 -387
  77. package/vendor/raylib/projects/VS2019/examples/physics_restitution.vcxproj +0 -387
  78. package/vendor/raylib/projects/VS2019/examples/physics_shatter.vcxproj +0 -387
  79. package/vendor/raylib/projects/VS2019/examples/raudio_standalone.vcxproj +0 -387
  80. package/vendor/raylib/projects/VS2019/examples/rlgl_standalone.vcxproj +0 -391
  81. package/vendor/raylib/projects/VS2019/examples/shaders_basic_lighting.vcxproj +0 -387
  82. package/vendor/raylib/projects/VS2019/examples/shaders_custom_uniform.vcxproj +0 -387
  83. package/vendor/raylib/projects/VS2019/examples/shaders_eratosthenes.vcxproj +0 -387
  84. package/vendor/raylib/projects/VS2019/examples/shaders_fog.vcxproj +0 -387
  85. package/vendor/raylib/projects/VS2019/examples/shaders_hot_reloading.vcxproj +0 -387
  86. package/vendor/raylib/projects/VS2019/examples/shaders_julia_set.vcxproj +0 -387
  87. package/vendor/raylib/projects/VS2019/examples/shaders_mesh_instancing.vcxproj +0 -387
  88. package/vendor/raylib/projects/VS2019/examples/shaders_model_shader.vcxproj +0 -387
  89. package/vendor/raylib/projects/VS2019/examples/shaders_multi_sample2d.vcxproj +0 -387
  90. package/vendor/raylib/projects/VS2019/examples/shaders_palette_switch.vcxproj +0 -387
  91. package/vendor/raylib/projects/VS2019/examples/shaders_postprocessing.vcxproj +0 -387
  92. package/vendor/raylib/projects/VS2019/examples/shaders_raymarching.vcxproj +0 -387
  93. package/vendor/raylib/projects/VS2019/examples/shaders_shapes_textures.vcxproj +0 -387
  94. package/vendor/raylib/projects/VS2019/examples/shaders_simple_mask.vcxproj +0 -387
  95. package/vendor/raylib/projects/VS2019/examples/shaders_spotlight.vcxproj +0 -387
  96. package/vendor/raylib/projects/VS2019/examples/shaders_texture_drawing.vcxproj +0 -387
  97. package/vendor/raylib/projects/VS2019/examples/shaders_texture_waves.vcxproj +0 -387
  98. package/vendor/raylib/projects/VS2019/examples/shapes_basic_shapes.vcxproj +0 -387
  99. package/vendor/raylib/projects/VS2019/examples/shapes_bouncing_ball.vcxproj +0 -387
  100. package/vendor/raylib/projects/VS2019/examples/shapes_collision_area.vcxproj +0 -387
  101. package/vendor/raylib/projects/VS2019/examples/shapes_colors_palette.vcxproj +0 -387
  102. package/vendor/raylib/projects/VS2019/examples/shapes_draw_circle_sector.vcxproj +0 -387
  103. package/vendor/raylib/projects/VS2019/examples/shapes_draw_rectangle_rounded.vcxproj +0 -387
  104. package/vendor/raylib/projects/VS2019/examples/shapes_draw_ring.vcxproj +0 -387
  105. package/vendor/raylib/projects/VS2019/examples/shapes_easings_ball_anim.vcxproj +0 -387
  106. package/vendor/raylib/projects/VS2019/examples/shapes_easings_box_anim.vcxproj +0 -387
  107. package/vendor/raylib/projects/VS2019/examples/shapes_easings_rectangle_array.vcxproj +0 -387
  108. package/vendor/raylib/projects/VS2019/examples/shapes_following_eyes.vcxproj +0 -387
  109. package/vendor/raylib/projects/VS2019/examples/shapes_lines_bezier.vcxproj +0 -387
  110. package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib.vcxproj +0 -387
  111. package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib_anim.vcxproj +0 -387
  112. package/vendor/raylib/projects/VS2019/examples/shapes_rectangle_scaling.vcxproj +0 -387
  113. package/vendor/raylib/projects/VS2019/examples/text_font_filters.vcxproj +0 -387
  114. package/vendor/raylib/projects/VS2019/examples/text_font_loading.vcxproj +0 -387
  115. package/vendor/raylib/projects/VS2019/examples/text_font_sdf.vcxproj +0 -387
  116. package/vendor/raylib/projects/VS2019/examples/text_font_spritefont.vcxproj +0 -387
  117. package/vendor/raylib/projects/VS2019/examples/text_format_text.vcxproj +0 -387
  118. package/vendor/raylib/projects/VS2019/examples/text_input_box.vcxproj +0 -387
  119. package/vendor/raylib/projects/VS2019/examples/text_raylib_fonts.vcxproj +0 -387
  120. package/vendor/raylib/projects/VS2019/examples/text_rectangle_bounds.vcxproj +0 -387
  121. package/vendor/raylib/projects/VS2019/examples/text_unicode.vcxproj +0 -387
  122. package/vendor/raylib/projects/VS2019/examples/text_writing_anim.vcxproj +0 -387
  123. package/vendor/raylib/projects/VS2019/examples/textures_background_scrolling.vcxproj +0 -387
  124. package/vendor/raylib/projects/VS2019/examples/textures_blend_modes.vcxproj +0 -387
  125. package/vendor/raylib/projects/VS2019/examples/textures_bunnymark.vcxproj +0 -387
  126. package/vendor/raylib/projects/VS2019/examples/textures_draw_tiled.vcxproj +0 -387
  127. package/vendor/raylib/projects/VS2019/examples/textures_image_drawing.vcxproj +0 -387
  128. package/vendor/raylib/projects/VS2019/examples/textures_image_generation.vcxproj +0 -387
  129. package/vendor/raylib/projects/VS2019/examples/textures_image_loading.vcxproj +0 -387
  130. package/vendor/raylib/projects/VS2019/examples/textures_image_processing.vcxproj +0 -387
  131. package/vendor/raylib/projects/VS2019/examples/textures_image_text.vcxproj +0 -387
  132. package/vendor/raylib/projects/VS2019/examples/textures_logo_raylib.vcxproj +0 -387
  133. package/vendor/raylib/projects/VS2019/examples/textures_mouse_painting.vcxproj +0 -387
  134. package/vendor/raylib/projects/VS2019/examples/textures_npatch_drawing.vcxproj +0 -387
  135. package/vendor/raylib/projects/VS2019/examples/textures_particles_blending.vcxproj +0 -387
  136. package/vendor/raylib/projects/VS2019/examples/textures_raw_data.vcxproj +0 -387
  137. package/vendor/raylib/projects/VS2019/examples/textures_rectangle.vcxproj +0 -387
  138. package/vendor/raylib/projects/VS2019/examples/textures_sprite_button.vcxproj +0 -387
  139. package/vendor/raylib/projects/VS2019/examples/textures_sprite_explosion.vcxproj +0 -387
  140. package/vendor/raylib/projects/VS2019/examples/textures_srcrec_dstrec.vcxproj +0 -387
  141. package/vendor/raylib/projects/VS2019/examples/textures_to_image.vcxproj +0 -387
  142. package/vendor/raylib/projects/VS2019/raylib/raylib.vcxproj +0 -341
  143. package/vendor/raylib/projects/VS2019/raylib.sln +0 -2274
  144. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +0 -226
  145. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +0 -10
  146. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +0 -4
  147. package/vendor/raylib/projects/VS2019-Android/raylib_android.sln +0 -75
package/CMakeLists.txt CHANGED
@@ -37,7 +37,7 @@ set(KOFFI_SRC
37
37
  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
38
38
  if(WIN32)
39
39
  list(APPEND KOFFI_SRC src/call_x64_win_fwd.asm)
40
- elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
40
+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
41
41
  list(APPEND KOFFI_SRC src/call_arm64_fwd.S)
42
42
  else()
43
43
  list(APPEND KOFFI_SRC src/call_x64_sysv_fwd.S)
package/README.md CHANGED
@@ -1,145 +1,111 @@
1
1
  # Table of contents
2
2
 
3
3
  - [Introduction](#introduction)
4
+ - [Get started](#get-started)
4
5
  - [Benchmarks](#benchmarks)
5
6
  * [atoi results](#atoi-results)
6
7
  * [Raylib results](#raylib-results)
7
- - [Installation](#installation)
8
+ - [Tests](#tests)
9
+ - [Compilation](#compilation)
8
10
  * [Windows](#windows)
9
11
  * [Other platforms](#other-platforms)
10
- - [Get started](#get-started)
11
- - [Tests](#tests)
12
12
 
13
13
  # Introduction
14
14
 
15
- Koffi is a fast and easy-to-use FFI module for Node.js, with support for complex data types such as structs.
16
-
17
- The following platforms __are officially supported and tested__ at the moment:
18
-
19
- * Windows x86 *(cdecl, stdcall, fastcall)*
20
- * Windows x86_64
21
- * Linux x86
22
- * Linux x86_64
23
- * Linux ARM32+VFP Little Endian
24
- * Linux ARM64 Little Endian
25
- * FreeBSD x86
26
- * FreeBSD x86_64
27
- * FreeBSD ARM64 Little Endian
28
- * macOS x86_64
15
+ Koffi is a fast and easy-to-use FFI module for Node.js, with support for primitive and aggregate data types (structs), both by reference (pointer) and by value.
29
16
 
30
- The following platforms will __soon be officially supported__, when I can get my hand on a machine...:
17
+ After the release of version 1.0, the following features are planned:
31
18
 
32
- * macOS ARM64
19
+ * 1.1: C to JS callbacks
20
+ * 1.2: Support fixed array types
33
21
 
34
- The following platforms __may be supported__ but are not tested:
22
+ The following platforms __are officially supported and tested__ at the moment:
35
23
 
36
- * Linux ARM32 (full software FP) Little Endian
37
- * NetBSD x86_64
38
- * NetBSD ARM64
39
- * OpenBSD x86_64
40
- * OpenBSD ARM64
24
+ Platoform | Architecture | JS to C | C to JS (callback) | Pre-built binary
25
+ --------- | -------------------------------- | ------- | ------------------ | ----------------
26
+ Windows | x86 (cdecl, stdcall, fastcall) | 🟩 | 🟥 | Yes ✓
27
+ Windows | x86_64 | 🟩 | 🟥 | Yes ✓
28
+ Linux | x86 | 🟩 | 🟥 | Yes ✓
29
+ Linux | x86_64 | 🟩 | 🟥 | Yes ✓
30
+ Linux | ARM32+VFP Little Endian | 🟩 | 🟥 | Yes ✓
31
+ Linux | ARM64 Little Endian | 🟩 | 🟥 | Yes ✓
32
+ FreeBSD | x86 | 🟩 | 🟥 | Yes ✓
33
+ FreeBSD | x86_64 | 🟩 | 🟥 | Yes ✓
34
+ FreeBSD | ARM64 Little Endian | 🟩 | 🟥 | Yes ✓
35
+ macOS | x86_64 | 🟩 | 🟥 | Yes ✓
36
+ macOS | ARM64 (M1) Little Endian | 🟩 | 🟥 | No x
37
+ NetBSD | x86_64 | 🟧 | 🟥 | No x
38
+ NetBSD | ARM64 Little Endian | 🟧 | 🟥 | No x
39
+ OpenBSD | x86_64 | 🟧 | 🟥 | No x
40
+ OpenBSD | ARM64 Little Endian | 🟧 | 🟥 | No x
41
+
42
+ 🟩 Tested, fully operational
43
+ 🟧 May work, but not actively tested
44
+ 🟥 Does not work yet
41
45
 
42
46
  This is still in development, bugs are to expected. More tests will come in the near future.
43
47
 
44
- # Benchmarks
45
-
46
- In order to run it, go to `koffi/benchmark` and run `../../cnoke/cnoke.js` (or `node ..\..\cnoke\cnoke.js` on Windows) before doing anything else.
47
-
48
- Once this is done, you can execute each implementation, e.g. `build/atoi_cc` or `./atoi_koffi.js`. You can optionally define a custom number of iterations, e.g. `./atoi_koffi.js 10000000`.
49
-
50
- ## atoi results
51
-
52
- This test is based around repeated calls to a simple standard C function atoi, and has three implementations:
53
- - the first one is the reference, it calls atoi through an N-API module, and is close to the theoretical limit of a perfect (no overhead) Node.js > C FFI implementation.
54
- - the second one calls atoi through Koffi
55
- - the third one uses the official Node.js FFI implementation, node-ffi-napi
56
-
57
- Because atoi is a small call, the FFI overhead is clearly visible.
58
-
59
- ### Linux
60
-
61
- The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 5800H 16G):
62
-
63
- Benchmark | Iterations | Total time | Overhead
64
- ------------- | ---------- | ----------- | ----------
65
- atoi_napi | 20000000 | 1.10s | (baseline)
66
- atoi_koffi | 20000000 | 1.91s | x1.73
67
- atoi_node_ffi | 20000000 | 640.49s | x582
68
-
69
- ### Windows
70
-
71
- The results below were measured on my x86_64 Windows machine (AMD® Ryzen™ 7 5800H 16G):
72
-
73
- Benchmark | Iterations | Total time | Overhead
74
- ------------- | ---------- | ----------- | ----------
75
- atoi_napi | 20000000 | 1.94s | (baseline)
76
- atoi_koffi | 20000000 | 3.15s | x1.62
77
- atoi_node_ffi | 20000000 | 640.49s | x242
78
-
79
- ## Raylib results
80
-
81
- This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implemenetation, the baseline is a full C++ version of the code.
82
-
83
- ### Linux
84
-
85
- The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 5800H 16G):
48
+ # Get started
86
49
 
87
- Benchmark | Iterations | Total time | Overhead
88
- --------------- | ---------- | ----------- | ----------
89
- raylib_cc | 100 | 4.14s | (baseline)
90
- raylib_koffi | 100 | 6.25s | x1.51
91
- raylib_node_ffi | 100 | 27.13s | x6.55
50
+ Once you have installed koffi with `npm install koffi`, you can start by loading it this way:
92
51
 
93
- ### Windows
52
+ ```js
53
+ const koffi = require('koffi');
54
+ ```
94
55
 
95
- The results below were measured on my x86_64 Windows machine (AMD® Ryzen™ 7 5800H 16G):
56
+ Below you can find two examples:
96
57
 
97
- Benchmark | Iterations | Total time | Overhead
98
- --------------- | ---------- | ----------- | ----------
99
- raylib_cc | 100 | 8.39s | (baseline)
100
- raylib_koffi | 100 | 11.51s | x1.37
101
- raylib_node_ffi | 100 | 31.47s | x3.8
58
+ * The first one runs on Linux. The functions are declared with the C-like prototype language.
59
+ * The second one runs on Windows, and uses the node-ffi like syntax to declare functions.
60
+ * The third one is more complex and uses Raylib to animate "Hello World" in a window.
102
61
 
103
- # Installation
62
+ ## Small Linux example
104
63
 
105
- ## Windows
64
+ ```js
65
+ const koffi = require('koffi');
66
+ const lib = koffi.load('libc.so.6');
106
67
 
107
- First, make sure the following dependencies are met:
68
+ // Declare types
69
+ const timeval = koffi.struct('timeval', {
70
+ tv_sec: 'unsigned int',
71
+ tv_usec: 'unsigned int'
72
+ });
73
+ const timezone = koffi.struct('timezone', {
74
+ tz_minuteswest: 'int',
75
+ tz_dsttime: 'int'
76
+ });
108
77
 
109
- * The "Desktop development with C++" workload from [Visual Studio 2022 or 2019](https://visualstudio.microsoft.com/downloads/) or the "C++ build tools" workload from the [Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022), with the default optional components.
110
- * [CMake meta build system](https://cmake.org/)
111
- * [Node 16 LTS](https://nodejs.org/), but a newer version should work too
78
+ // Declare functions
79
+ const gettimeofday = lib.func('int gettimeofday(_Out_ timeval *tv, _Out_ timezone *tz)');
80
+ const printf = lib.func('int printf(const char *format, ...)');
112
81
 
113
- Once this is done, run this command from the project root:
82
+ let tv = {};
83
+ let tz = {};
84
+ gettimeofday(tv, tz);
114
85
 
115
- ```sh
116
- npm install koffi
86
+ printf('Hello World!, it is: %d\n', 'int', tv.tv_sec);
87
+ console.log(tz);
117
88
  ```
118
89
 
119
- ## Other platforms
120
-
121
- Make sure the following dependencies are met:
90
+ ## Small Windows example
122
91
 
123
- * `gcc` and `g++` >= 8.3 or newer
124
- * GNU Make 3.81 or newer
125
- * [CMake meta build system](https://cmake.org/)
92
+ ```js
93
+ const koffi = require('koffi');
94
+ const lib = koffi.load('user32.dll');
126
95
 
127
- Once these dependencies are met, simply run the follow command:
96
+ const MessageBoxA = lib.stdcall('MessageBoxA', 'int', ['void *', 'string', 'string', 'uint']);
97
+ const MB_ICONINFORMATION = 0x40;
128
98
 
129
- ```sh
130
- npm install koffi
99
+ MessageBoxA(null, 'Hello', 'Foobar', MB_ICONINFORMATION);
131
100
  ```
132
101
 
133
- # Get started
134
-
135
- This section assumes you know how to build C shared libraries.
136
-
137
102
  ## Raylib example
138
103
 
139
- This examples illustrates how to use Koffi with a Raylib shared library:
104
+ This section assumes you know how to build C shared libraries, such as Raylib. You may need to fix the URL to the library before you can do anything.
140
105
 
141
106
  ```js
142
107
  const koffi = require('koffi');
108
+ let lib = koffi.load('raylib.dll'); // Fix path if needed
143
109
 
144
110
  const Color = koffi.struct('Color', {
145
111
  r: 'uchar',
@@ -193,9 +159,6 @@ const Font = koffi.struct('Font', {
193
159
  glyphs: koffi.pointer(GlyphInfo)
194
160
  });
195
161
 
196
- // Fix the path to Raylib DLL if needed
197
- let lib = koffi.load('build/raylib' + koffi.extension);
198
-
199
162
  // Classic function declaration
200
163
  const InitWindow = lib.func('InitWindow', 'void', ['int', 'int', 'string']);
201
164
  const SetTargetFPS = lib.func('SetTargetFPS', 'void', ['int']);
@@ -246,19 +209,84 @@ while (!WindowShouldClose()) {
246
209
 
247
210
  ```
248
211
 
249
- ## Win32 stdcall example
212
+ # Extra features
250
213
 
251
- ```js
252
- const koffi = require('koffi');
214
+ ## Variadic functions
253
215
 
254
- let lib = koffi.load('user32.dll');
216
+ Variadic functions are declared with an ellipsis as the last argument.
255
217
 
256
- const MessageBoxA = lib.stdcall('MessageBoxA', 'int', ['void *', 'string', 'string', 'uint']);
257
- const MB_ICONINFORMATION = 0x40;
218
+ In order to call a variadic function, you must provide two Javascript arguments for each C parameter,
219
+ the first one is the expected type and the second one is the value.
258
220
 
259
- MessageBoxA(null, 'Hello', 'Foobar', MB_ICONINFORMATION);
221
+ ```js
222
+ const printf = lib.func('printf', 'int', ['string', '...']);
223
+
224
+ printf('Integer %d, double %g, string %s', 'int', 6, 'double', 8.5, 'string', 'THE END');
260
225
  ```
261
226
 
227
+ ## Callbacks
228
+
229
+ Koffi does not yet support passing JS functions as callbacks. This is planned for version 1.1.
230
+
231
+ # Benchmarks
232
+
233
+ In order to run it, go to `koffi/benchmark` and run `../../cnoke/cnoke.js` (or `node ..\..\cnoke\cnoke.js` on Windows) before doing anything else.
234
+
235
+ Once this is done, you can execute each implementation, e.g. `build/atoi_cc` or `./atoi_koffi.js`. You can optionally define a custom number of iterations, e.g. `./atoi_koffi.js 10000000`.
236
+
237
+ ## atoi results
238
+
239
+ This test is based around repeated calls to a simple standard C function atoi, and has three implementations:
240
+ - the first one is the reference, it calls atoi through an N-API module, and is close to the theoretical limit of a perfect (no overhead) Node.js > C FFI implementation.
241
+ - the second one calls atoi through Koffi
242
+ - the third one uses the official Node.js FFI implementation, node-ffi-napi
243
+
244
+ Because atoi is a small call, the FFI overhead is clearly visible.
245
+
246
+ ### Linux
247
+
248
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 5800H 16G):
249
+
250
+ Benchmark | Iterations | Total time | Overhead
251
+ ------------- | ---------- | ----------- | ----------
252
+ atoi_napi | 20000000 | 1.10s | (baseline)
253
+ atoi_koffi | 20000000 | 1.91s | x1.73
254
+ atoi_node_ffi | 20000000 | 640.49s | x582
255
+
256
+ ### Windows
257
+
258
+ The results below were measured on my x86_64 Windows machine (AMD® Ryzen™ 7 5800H 16G):
259
+
260
+ Benchmark | Iterations | Total time | Overhead
261
+ ------------- | ---------- | ----------- | ----------
262
+ atoi_napi | 20000000 | 1.94s | (baseline)
263
+ atoi_koffi | 20000000 | 3.15s | x1.62
264
+ atoi_node_ffi | 20000000 | 640.49s | x242
265
+
266
+ ## Raylib results
267
+
268
+ This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implemenetation, the baseline is a full C++ version of the code.
269
+
270
+ ### Linux
271
+
272
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 5800H 16G):
273
+
274
+ Benchmark | Iterations | Total time | Overhead
275
+ --------------- | ---------- | ----------- | ----------
276
+ raylib_cc | 100 | 4.14s | (baseline)
277
+ raylib_koffi | 100 | 6.25s | x1.51
278
+ raylib_node_ffi | 100 | 27.13s | x6.55
279
+
280
+ ### Windows
281
+
282
+ The results below were measured on my x86_64 Windows machine (AMD® Ryzen™ 7 5800H 16G):
283
+
284
+ Benchmark | Iterations | Total time | Overhead
285
+ --------------- | ---------- | ----------- | ----------
286
+ raylib_cc | 100 | 8.39s | (baseline)
287
+ raylib_koffi | 100 | 11.51s | x1.37
288
+ raylib_node_ffi | 100 | 31.47s | x3.8
289
+
262
290
  # Tests
263
291
 
264
292
  Koffi is tested on multiple architectures using emulated (accelerated when possible) QEMU machines. First, you need to install qemu packages, such as `qemu-system` (or even `qemu-system-gui`) on Ubuntu.
@@ -314,4 +342,36 @@ Each machine is configured to run a VNC server available locally, which you can
314
342
 
315
343
  ```sh
316
344
  node qemu.js info debian_x64
317
- ```
345
+ ```
346
+
347
+ # Compilation
348
+
349
+ We provide prebuilt binaries, packaged in the NPM archive, so in most cases it should be as simple as `npm install koffi`. If you want to hack Koffi or use a specific platform, follow the instructions below.
350
+
351
+ ## Windows
352
+
353
+ First, make sure the following dependencies are met:
354
+
355
+ * The "Desktop development with C++" workload from [Visual Studio 2022 or 2019](https://visualstudio.microsoft.com/downloads/) or the "C++ build tools" workload from the [Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022), with the default optional components.
356
+ * [CMake meta build system](https://cmake.org/)
357
+ * [Node 16 LTS](https://nodejs.org/), but a newer version should work too
358
+
359
+ Once this is done, run this command from the project root:
360
+
361
+ ```sh
362
+ npm install koffi
363
+ ```
364
+
365
+ ## Other platforms
366
+
367
+ Make sure the following dependencies are met:
368
+
369
+ * `gcc` and `g++` >= 8.3 or newer
370
+ * GNU Make 3.81 or newer
371
+ * [CMake meta build system](https://cmake.org/)
372
+
373
+ Once these dependencies are met, simply run the follow command:
374
+
375
+ ```sh
376
+ npm install koffi
377
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "0.9.45",
3
+ "version": "1.0.0",
4
4
  "description": "Fast and simple FFI (foreign function interface) for Node.js",
5
5
  "keywords": [
6
6
  "foreign",
@@ -18,7 +18,7 @@
18
18
  "author": "Niels Martignène <niels.martignene@protonmail.com>",
19
19
  "main": "src/index.js",
20
20
  "scripts": {
21
- "install": "cnoke --prebuild qemu/build/{{version}}/koffi_{{platform}}_{{arch}}.tar.gz",
21
+ "install": "cnoke --prebuild build/qemu/{{version}}/koffi_{{platform}}_{{arch}}.tar.gz",
22
22
  "test": "node qemu/qemu.js",
23
23
  "prepublishOnly": "node qemu/qemu.js pack"
24
24
  },
@@ -48,6 +48,6 @@
48
48
  "LICENSE.txt",
49
49
  "README.md",
50
50
  "CMakeLists.txt",
51
- "qemu/build/*/*.tar.gz"
51
+ "build/qemu/*/*.tar.gz"
52
52
  ]
53
53
  }
package/src/call_arm32.cc CHANGED
@@ -39,7 +39,6 @@ extern "C" HfaRet ForwardCallXDDDD(const void *func, uint8_t *sp);
39
39
 
40
40
  static bool IsHFA(const TypeInfo *type)
41
41
  {
42
- #ifdef __ARM_PCS_VFP
43
42
  if (type->primitive != PrimitiveKind::Record)
44
43
  return false;
45
44
 
@@ -55,9 +54,6 @@ static bool IsHFA(const TypeInfo *type)
55
54
  }
56
55
 
57
56
  return true;
58
- #else
59
- return false;
60
- #endif
61
57
  }
62
58
 
63
59
  bool AnalyseFunction(InstanceData *, FunctionInfo *func)
@@ -110,12 +106,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
110
106
  case PrimitiveKind::Float32:
111
107
  case PrimitiveKind::Float64: {
112
108
  Size need = param.type->size / 4;
113
-
114
- #ifdef __ARM_PCS_VFP
115
109
  bool vfp = !param.variadic;
116
- #else
117
- bool vfp = false;
118
- #endif
119
110
 
120
111
  if (vfp) {
121
112
  if (need <= vec_avail) {
package/src/call_arm64.cc CHANGED
@@ -88,6 +88,11 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
88
88
  case PrimitiveKind::UInt64:
89
89
  case PrimitiveKind::String:
90
90
  case PrimitiveKind::Pointer: {
91
+ #ifdef __APPLE__
92
+ if (param.variadic)
93
+ break;
94
+ #endif
95
+
91
96
  if (gpr_avail) {
92
97
  param.gpr_count = 1;
93
98
  gpr_avail--;
@@ -96,6 +101,11 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
96
101
 
97
102
  case PrimitiveKind::Float32:
98
103
  case PrimitiveKind::Float64: {
104
+ #ifdef __APPLE__
105
+ if (param.variadic)
106
+ break;
107
+ #endif
108
+
99
109
  if (vec_avail) {
100
110
  param.vec_count = 1;
101
111
  vec_avail--;
@@ -103,6 +113,13 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
103
113
  } break;
104
114
 
105
115
  case PrimitiveKind::Record: {
116
+ #ifdef __APPLE__
117
+ if (param.variadic) {
118
+ param.use_memory = (param.type->size > 16);
119
+ break;
120
+ }
121
+ #endif
122
+
106
123
  if (IsHFA(param.type)) {
107
124
  int vec_count = (int)param.type->members.len;
108
125