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.
- package/CMakeLists.txt +1 -1
- package/README.md +173 -113
- package/build/qemu/1.0.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.0/koffi_win32_x64.tar.gz +0 -0
- package/package.json +3 -3
- package/src/call_arm32.cc +0 -9
- package/src/call_arm64.cc +17 -0
- package/qemu/build/0.9.45/koffi_freebsd_arm64.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_freebsd_ia32.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_freebsd_x64.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_linux_arm.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_linux_arm64.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_linux_ia32.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_linux_x64.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_win32_ia32.tar.gz +0 -0
- package/qemu/build/0.9.45/koffi_win32_x64.tar.gz +0 -0
- package/vendor/raylib/projects/VS2019/examples/audio_module_playing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/audio_multichannel_sound.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/audio_music_stream.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/audio_raw_stream.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/audio_sound_loading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_2d_camera.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_2d_camera_platformer.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_3d_camera_first_person.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_3d_camera_free.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_3d_camera_mode.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_3d_picking.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_basic_window.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_custom_logging.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_drop_files.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_gamepad.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_gestures.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_keys.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_mouse.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_mouse_wheel.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_input_multitouch.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_loading_thread.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_quat_conversion.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_random_values.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_scissor_test.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_split_screen.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_storage_values.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_vr_simulator.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_window_flags.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_window_letterbox.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/core_world_screen.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/easings_testbed.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/embedded_files_loading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_animation.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_billboard.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_box_collisions.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_cubicmap.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_first_person_maze.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_geometric_shapes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_heightmap.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_loading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_loading_gltf.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_loading_vox.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_mesh_generation.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_mesh_picking.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_orthographic_projection.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_rlgl_solar_system.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_skybox.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_waving_cubes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/models_yaw_pitch_roll.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/physics_demo.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/physics_friction.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/physics_movement.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/physics_restitution.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/physics_shatter.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/raudio_standalone.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/rlgl_standalone.vcxproj +0 -391
- package/vendor/raylib/projects/VS2019/examples/shaders_basic_lighting.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_custom_uniform.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_eratosthenes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_fog.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_hot_reloading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_julia_set.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_mesh_instancing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_model_shader.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_multi_sample2d.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_palette_switch.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_postprocessing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_raymarching.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_shapes_textures.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_simple_mask.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_spotlight.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_texture_drawing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shaders_texture_waves.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_basic_shapes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_bouncing_ball.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_collision_area.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_colors_palette.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_draw_circle_sector.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_draw_rectangle_rounded.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_draw_ring.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_easings_ball_anim.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_easings_box_anim.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_easings_rectangle_array.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_following_eyes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_lines_bezier.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib_anim.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/shapes_rectangle_scaling.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_font_filters.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_font_loading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_font_sdf.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_font_spritefont.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_format_text.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_input_box.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_raylib_fonts.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_rectangle_bounds.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_unicode.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/text_writing_anim.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_background_scrolling.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_blend_modes.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_bunnymark.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_draw_tiled.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_image_drawing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_image_generation.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_image_loading.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_image_processing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_image_text.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_logo_raylib.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_mouse_painting.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_npatch_drawing.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_particles_blending.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_raw_data.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_rectangle.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_sprite_button.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_sprite_explosion.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_srcrec_dstrec.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/examples/textures_to_image.vcxproj +0 -387
- package/vendor/raylib/projects/VS2019/raylib/raylib.vcxproj +0 -341
- package/vendor/raylib/projects/VS2019/raylib.sln +0 -2274
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +0 -226
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +0 -10
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +0 -4
- 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
|
|
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
|
-
- [
|
|
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
|
|
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
|
-
|
|
17
|
+
After the release of version 1.0, the following features are planned:
|
|
31
18
|
|
|
32
|
-
*
|
|
19
|
+
* 1.1: C to JS callbacks
|
|
20
|
+
* 1.2: Support fixed array types
|
|
33
21
|
|
|
34
|
-
The following platforms
|
|
22
|
+
The following platforms __are officially supported and tested__ at the moment:
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
52
|
+
```js
|
|
53
|
+
const koffi = require('koffi');
|
|
54
|
+
```
|
|
94
55
|
|
|
95
|
-
|
|
56
|
+
Below you can find two examples:
|
|
96
57
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
62
|
+
## Small Linux example
|
|
104
63
|
|
|
105
|
-
|
|
64
|
+
```js
|
|
65
|
+
const koffi = require('koffi');
|
|
66
|
+
const lib = koffi.load('libc.so.6');
|
|
106
67
|
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
82
|
+
let tv = {};
|
|
83
|
+
let tz = {};
|
|
84
|
+
gettimeofday(tv, tz);
|
|
114
85
|
|
|
115
|
-
|
|
116
|
-
|
|
86
|
+
printf('Hello World!, it is: %d\n', 'int', tv.tv_sec);
|
|
87
|
+
console.log(tz);
|
|
117
88
|
```
|
|
118
89
|
|
|
119
|
-
##
|
|
120
|
-
|
|
121
|
-
Make sure the following dependencies are met:
|
|
90
|
+
## Small Windows example
|
|
122
91
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
92
|
+
```js
|
|
93
|
+
const koffi = require('koffi');
|
|
94
|
+
const lib = koffi.load('user32.dll');
|
|
126
95
|
|
|
127
|
-
|
|
96
|
+
const MessageBoxA = lib.stdcall('MessageBoxA', 'int', ['void *', 'string', 'string', 'uint']);
|
|
97
|
+
const MB_ICONINFORMATION = 0x40;
|
|
128
98
|
|
|
129
|
-
|
|
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
|
|
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
|
-
|
|
212
|
+
# Extra features
|
|
250
213
|
|
|
251
|
-
|
|
252
|
-
const koffi = require('koffi');
|
|
214
|
+
## Variadic functions
|
|
253
215
|
|
|
254
|
-
|
|
216
|
+
Variadic functions are declared with an ellipsis as the last argument.
|
|
255
217
|
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
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
|
+
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "0.
|
|
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/
|
|
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
|
|
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
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|