koffi 2.1.0-beta.3 → 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.
- package/ChangeLog.md +2 -1
- package/build/qemu/2.1.0/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_x64.tar.gz +0 -0
- package/doc/benchmarks.md +14 -14
- package/doc/benchmarks.xlsx +0 -0
- package/doc/index.rst +2 -2
- package/doc/static/perf_linux_20220812.png +0 -0
- package/doc/static/perf_windows_20220812.png +0 -0
- package/doc/types.md +10 -12
- package/package.json +2 -2
- package/qemu/registry/machines.json +2 -2
- package/qemu/registry/sha256sum.txt +2 -2
- package/src/abi_arm32.cc +23 -55
- package/src/abi_arm64.cc +22 -54
- package/src/abi_riscv64.cc +20 -52
- package/src/abi_x64_sysv.cc +20 -52
- package/src/abi_x64_win.cc +20 -52
- package/src/abi_x86.cc +24 -56
- package/src/call.cc +117 -143
- package/src/call.hh +4 -4
- package/src/ffi.cc +16 -4
- package/src/util.hh +0 -20
- package/test/callbacks.js +3 -3
- package/test/misc.c +2 -2
- package/test/sync.js +2 -2
- package/vendor/libcc/libcc.cc +75 -55
- package/vendor/libcc/libcc.hh +306 -255
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +226 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +10 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +4 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android.sln +75 -0
- package/vendor/raylib/projects/VS2022/examples/audio_module_playing.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_multichannel_sound.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_music_stream.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_raw_stream.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_sound_loading.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_stream_effects.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera_mouse_zoom.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera_platformer.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_first_person.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_free.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_mode.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_picking.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_basic_screen_manager.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_basic_window.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_custom_frame_control.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_custom_logging.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_drop_files.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_gamepad.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_gestures.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_keys.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_mouse.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_mouse_wheel.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_multitouch.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_loading_thread.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_random_values.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_scissor_test.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_split_screen.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_storage_values.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_vr_simulator.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_flags.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_letterbox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_should_close.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_world_screen.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/easings_testbed.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/embedded_files_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_animation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_billboard.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_box_collisions.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_cubicmap.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_first_person_maze.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_geometric_shapes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_heightmap.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading_gltf.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading_vox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_mesh_generation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_mesh_picking.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_orthographic_projection.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_rlgl_solar_system.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_skybox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_waving_cubes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_yaw_pitch_roll.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/rlgl_compute_shaders.vcxproj +391 -0
- package/vendor/raylib/projects/VS2022/examples/rlgl_standalone.vcxproj +391 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_basic_lighting.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_custom_uniform.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_eratosthenes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_fog.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_hot_reloading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_julia_set.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_mesh_instancing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_model_shader.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_multi_sample2d.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_palette_switch.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_postprocessing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_raymarching.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_shapes_textures.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_simple_mask.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_spotlight.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_texture_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_texture_waves.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_basic_shapes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_bouncing_ball.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_collision_area.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_colors_palette.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_circle_sector.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_rectangle_rounded.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_ring.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_ball_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_box_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_rectangle_array.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_following_eyes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_lines_bezier.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_rectangle_scaling.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_codepoints_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_draw_3d.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_filters.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_sdf.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_spritefont.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_format_text.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_input_box.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_raylib_fonts.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_rectangle_bounds.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_unicode.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_writing_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_background_scrolling.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_blend_modes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_bunnymark.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_draw_tiled.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_fog_of_war.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_gif_player.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_generation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_processing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_text.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_logo_raylib.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_mouse_painting.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_npatch_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_particles_blending.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_polygon.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_raw_data.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_button.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_explosion.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_srcrec_dstrec.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_to_image.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/raylib/raylib.vcxproj +340 -0
- package/vendor/raylib/projects/VS2022/raylib.sln +2347 -0
- package/build/qemu/2.1.0-beta.3/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_x64.tar.gz +0 -0
- package/doc/dist/doctrees/benchmarks.doctree +0 -0
- package/doc/dist/doctrees/changes.doctree +0 -0
- package/doc/dist/doctrees/contribute.doctree +0 -0
- package/doc/dist/doctrees/environment.pickle +0 -0
- package/doc/dist/doctrees/functions.doctree +0 -0
- package/doc/dist/doctrees/index.doctree +0 -0
- package/doc/dist/doctrees/memory.doctree +0 -0
- package/doc/dist/doctrees/platforms.doctree +0 -0
- package/doc/dist/doctrees/start.doctree +0 -0
- package/doc/dist/doctrees/types.doctree +0 -0
- package/doc/dist/html/.buildinfo +0 -4
- package/doc/dist/html/_sources/benchmarks.md.txt +0 -137
- package/doc/dist/html/_sources/changes.md.txt +0 -161
- package/doc/dist/html/_sources/contribute.md.txt +0 -127
- package/doc/dist/html/_sources/functions.md.txt +0 -421
- package/doc/dist/html/_sources/index.rst.txt +0 -39
- package/doc/dist/html/_sources/memory.md.txt +0 -32
- package/doc/dist/html/_sources/platforms.md.txt +0 -31
- package/doc/dist/html/_sources/start.md.txt +0 -100
- package/doc/dist/html/_sources/types.md.txt +0 -541
- package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +0 -134
- package/doc/dist/html/_static/basic.css +0 -932
- package/doc/dist/html/_static/bench_linux.png +0 -0
- package/doc/dist/html/_static/bench_windows.png +0 -0
- package/doc/dist/html/_static/custom.css +0 -22
- package/doc/dist/html/_static/debug.css +0 -69
- package/doc/dist/html/_static/doctools.js +0 -264
- package/doc/dist/html/_static/documentation_options.js +0 -14
- package/doc/dist/html/_static/file.png +0 -0
- package/doc/dist/html/_static/jquery-3.6.0.js +0 -10881
- package/doc/dist/html/_static/jquery.js +0 -2
- package/doc/dist/html/_static/language_data.js +0 -199
- package/doc/dist/html/_static/minus.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220627.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220628.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220627.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220628.png +0 -0
- package/doc/dist/html/_static/plus.png +0 -0
- package/doc/dist/html/_static/pygments.css +0 -252
- package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
- package/doc/dist/html/_static/scripts/furo.js +0 -3
- package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +0 -7
- package/doc/dist/html/_static/scripts/furo.js.map +0 -1
- package/doc/dist/html/_static/searchtools.js +0 -531
- package/doc/dist/html/_static/skeleton.css +0 -296
- package/doc/dist/html/_static/styles/furo-extensions.css +0 -2
- package/doc/dist/html/_static/styles/furo-extensions.css.map +0 -1
- package/doc/dist/html/_static/styles/furo.css +0 -2
- package/doc/dist/html/_static/styles/furo.css.map +0 -1
- package/doc/dist/html/_static/underscore-1.13.1.js +0 -2042
- package/doc/dist/html/_static/underscore.js +0 -6
- package/doc/dist/html/benchmarks.html +0 -571
- package/doc/dist/html/changes.html +0 -686
- package/doc/dist/html/contribute.html +0 -403
- package/doc/dist/html/functions.html +0 -718
- package/doc/dist/html/genindex.html +0 -253
- package/doc/dist/html/index.html +0 -359
- package/doc/dist/html/memory.html +0 -346
- package/doc/dist/html/objects.inv +0 -0
- package/doc/dist/html/platforms.html +0 -371
- package/doc/dist/html/search.html +0 -261
- package/doc/dist/html/searchindex.js +0 -1
- package/doc/dist/html/start.html +0 -384
- package/doc/dist/html/types.html +0 -1061
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
# Functions
|
|
2
|
-
|
|
3
|
-
## Function definitions
|
|
4
|
-
|
|
5
|
-
To declare functions, start by loading the shared library with `koffi.load(filename)`.
|
|
6
|
-
|
|
7
|
-
```js
|
|
8
|
-
const koffi = require('koffi');
|
|
9
|
-
const lib = koffi.load('/path/to/shared/library'); // File extension depends on platforms: .so, .dll, .dylib, etc.
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
You can use the returned object to load C functions from the library. To do so, you can use two syntaxes:
|
|
13
|
-
|
|
14
|
-
- The classic syntax, inspired by node-ffi
|
|
15
|
-
- C-like prototypes
|
|
16
|
-
|
|
17
|
-
### Classic syntax
|
|
18
|
-
|
|
19
|
-
To declare a function, you need to specify its non-mangled name, its return type, and its parameters. Use an ellipsis as the last parameter for variadic functions.
|
|
20
|
-
|
|
21
|
-
```js
|
|
22
|
-
const printf = lib.func('printf', 'int', ['str', '...']);
|
|
23
|
-
const atoi = lib.func('atoi', 'int', ['str']);
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Koffi automatically tries mangled names for non-standard x86 calling conventions. See the section on [calling conventions](#calling-conventions) for more information on this subject.
|
|
27
|
-
|
|
28
|
-
### C-like prototypes
|
|
29
|
-
|
|
30
|
-
If you prefer, you can declare functions using simple C-like prototype strings, as shown below:
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
const printf = lib.func('int printf(const char *fmt, ...)');
|
|
34
|
-
const atoi = lib.func('int atoi(str)'); // The parameter name is not used by Koffi, and optional
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
You can use `()` or `(void)` for functions that take no argument.
|
|
38
|
-
|
|
39
|
-
## Function calls
|
|
40
|
-
|
|
41
|
-
### Calling conventions
|
|
42
|
-
|
|
43
|
-
By default, calling a C function happens synchronously.
|
|
44
|
-
|
|
45
|
-
Most architectures only support one procedure call standard per process. The 32-bit x86 platform is an exception to this, and Koffi supports several x86 conventions:
|
|
46
|
-
|
|
47
|
-
Convention | Classic form | Prototype form | Description
|
|
48
|
-
------------- | ----------------------------- | -------------- | -------------------------------------------------------------------
|
|
49
|
-
**Cdecl** | `koffi.cdecl` or `koffi.func` | _(default)_ | This is the default convention, and the only one on other platforms
|
|
50
|
-
**Stdcall** | `koffi.stdcall` | __stdcall | This convention is used extensively within the Win32 API
|
|
51
|
-
**Fastcall** | `koffi.fastcall` | __fastcall | Rarely used, uses ECX and EDX for first two parameters
|
|
52
|
-
**Thiscall** | `koffi.thiscall` | __thiscall | Rarely used, uses ECX for first parameter
|
|
53
|
-
|
|
54
|
-
You can safely use these on non-x86 platforms, they are simply ignored.
|
|
55
|
-
|
|
56
|
-
Below you can find a small example showing how to use a non-default calling convention, with the two syntaxes:
|
|
57
|
-
|
|
58
|
-
```js
|
|
59
|
-
const koffi = require('koffi');
|
|
60
|
-
const lib = koffi.load('user32.dll');
|
|
61
|
-
|
|
62
|
-
// The following two declarations are equivalent, and use stdcall on x86 (and the default ABI on other platforms)
|
|
63
|
-
const MessageBoxA_1 = lib.stdcall('MessageBoxA', 'int', ['void *', 'str', 'str', 'uint']);
|
|
64
|
-
const MessageBoxA_2 = lib.func('int __stdcall MessageBoxA(void *hwnd, str text, str caption, uint type)');
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Asynchronous calls
|
|
68
|
-
|
|
69
|
-
You can issue asynchronous calls by calling the function through its async member. In this case, you need to provide a callback function as the last argument, with `(err, res)` parameters.
|
|
70
|
-
|
|
71
|
-
```js
|
|
72
|
-
const koffi = require('koffi');
|
|
73
|
-
const lib = koffi.load('libc.so.6');
|
|
74
|
-
|
|
75
|
-
const atoi = lib.func('int atoi(const char *str)');
|
|
76
|
-
|
|
77
|
-
atoi.async('1257', (err, res) => {
|
|
78
|
-
console.log('Result:', res);
|
|
79
|
-
})
|
|
80
|
-
console.log('Hello World!');
|
|
81
|
-
|
|
82
|
-
// This program will print:
|
|
83
|
-
// Hello World!
|
|
84
|
-
// Result: 1257
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
These calls are executed by worker threads. It is **your responsibility to deal with data sharing issues** in the native code that may be caused by multi-threading.
|
|
88
|
-
|
|
89
|
-
You can easily convert this callback-style async function to a promise-based version with `util.promisify()` from the Node.js standard library.
|
|
90
|
-
|
|
91
|
-
Variadic functions cannot be called asynchronously.
|
|
92
|
-
|
|
93
|
-
### Variadic functions
|
|
94
|
-
|
|
95
|
-
Variadic functions are declared with an ellipsis as the last argument.
|
|
96
|
-
|
|
97
|
-
In order to call a variadic function, you must provide two Javascript arguments for each additional C parameter, the first one is the expected type and the second one is the value.
|
|
98
|
-
|
|
99
|
-
```js
|
|
100
|
-
const printf = lib.func('printf', 'int', ['str', '...']);
|
|
101
|
-
|
|
102
|
-
// The variadic arguments are: 6 (int), 8.5 (double), 'THE END' (const char *)
|
|
103
|
-
printf('Integer %d, double %g, str %s', 'int', 6, 'double', 8.5, 'str', 'THE END');
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
On x86 platforms, only the Cdecl convention can be used for variadic functions.
|
|
107
|
-
|
|
108
|
-
## Special considerations
|
|
109
|
-
|
|
110
|
-
### Output parameters
|
|
111
|
-
|
|
112
|
-
By default, Koffi will only forward arguments from Javascript to C. However, many C functions use pointer arguments for output values, or input/output values.
|
|
113
|
-
|
|
114
|
-
For simplicity, and because Javascript only has value semantics for primitive types, Koffi can marshal out (or in/out) two types of parameters:
|
|
115
|
-
|
|
116
|
-
- [Structs](types.md#struct-types) (to/from JS objects)
|
|
117
|
-
- [Opaque types](types.md#opaque-types)
|
|
118
|
-
|
|
119
|
-
In order to change an argument from input-only to output or input/output, use the following functions:
|
|
120
|
-
|
|
121
|
-
- `koffi.out()` on a pointer, e.g. `koffi.out(koffi.pointer(timeval))` (where timeval is a struct type)
|
|
122
|
-
- `koffi.inout()` for dual input/output parameters
|
|
123
|
-
|
|
124
|
-
The same can be done when declaring a function with a C-like prototype string, with the MSDN-like type qualifiers:
|
|
125
|
-
|
|
126
|
-
- `_Out_` for output parameters
|
|
127
|
-
- `_Inout_` for dual input/output parameters
|
|
128
|
-
|
|
129
|
-
#### Struct example
|
|
130
|
-
|
|
131
|
-
This example calls the POSIX function `gettimeofday()`, and uses the prototype-like syntax.
|
|
132
|
-
|
|
133
|
-
```js
|
|
134
|
-
const koffi = require('koffi');
|
|
135
|
-
const lib = koffi.load('libc.so.6');
|
|
136
|
-
|
|
137
|
-
const timeval = koffi.struct('timeval', {
|
|
138
|
-
tv_sec: 'unsigned int',
|
|
139
|
-
tv_usec: 'unsigned int'
|
|
140
|
-
});
|
|
141
|
-
const timezone = koffi.struct('timezone', {
|
|
142
|
-
tz_minuteswest: 'int',
|
|
143
|
-
tz_dsttime: 'int'
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// The _Out_ qualifiers instruct Koffi to marshal out the values
|
|
147
|
-
const gettimeofday = lib.func('int gettimeofday(_Out_ timeval *tv, _Out_ timezone *tz)');
|
|
148
|
-
|
|
149
|
-
let tv = {};
|
|
150
|
-
gettimeofday(tv, null);
|
|
151
|
-
|
|
152
|
-
console.log(tv);
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
#### Opaque type example
|
|
156
|
-
|
|
157
|
-
This example opens an in-memory SQLite database, and uses the node-ffi-style function declaration syntax.
|
|
158
|
-
|
|
159
|
-
```js
|
|
160
|
-
const koffi = require('koffi');
|
|
161
|
-
const lib = koffi.load('sqlite3.so');
|
|
162
|
-
|
|
163
|
-
const sqlite3 = koffi.opaque('sqlite3');
|
|
164
|
-
|
|
165
|
-
// Use koffi.out() on a double pointer to copy out (from C to JS) after the call
|
|
166
|
-
const sqlite3_open_v2 = lib.func('sqlite3_open_v2', 'int', ['str', koffi.out(koffi.pointer(sqlite3, 2)), 'int', 'str']);
|
|
167
|
-
const sqlite3_close_v2 = lib.func('sqlite3_close_v2', 'int', [koffi.pointer(sqlite3)]);
|
|
168
|
-
|
|
169
|
-
const SQLITE_OPEN_READWRITE = 0x2;
|
|
170
|
-
const SQLITE_OPEN_CREATE = 0x4;
|
|
171
|
-
|
|
172
|
-
let out = [null];
|
|
173
|
-
if (sqlite3_open_v2(':memory:', out, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, null) != 0)
|
|
174
|
-
throw new Error('Failed to open database');
|
|
175
|
-
let db = out[0];
|
|
176
|
-
|
|
177
|
-
sqlite3_close_v2(db);
|
|
178
|
-
```
|
|
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
|
-
|
|
242
|
-
### Heap-allocated values
|
|
243
|
-
|
|
244
|
-
*New in Koffi 2.0*
|
|
245
|
-
|
|
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.
|
|
247
|
-
|
|
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.
|
|
249
|
-
|
|
250
|
-
To avoid this, you can instruct Koffi to call a function on the original pointer once the conversion is done, by creating a **disposable type** with `koffi.dispose(name, type, func)`. This creates a type derived from another type, the only difference being that *func* gets called with the original pointer once the value has been converted and is not needed anymore.
|
|
251
|
-
|
|
252
|
-
The *name* can be omitted to create an anonymous disposable type. If *func* is omitted or is null, Koffi will use `koffi.free(ptr)` (which calls the standard C library *free* function under the hood).
|
|
253
|
-
|
|
254
|
-
```js
|
|
255
|
-
const AnonHeapStr = koffi.disposable('str'); // Anonymous type (cannot be used in function prototypes)
|
|
256
|
-
const NamedHeapStr = koffi.disposable('HeapStr', 'str'); // Same thing, but named so usable in function prototypes
|
|
257
|
-
const ExplicitFree = koffi.disposable('HeapStr16', 'str16', koffi.free); // You can specify any other JS function
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
The following example illustrates the use of a disposable type derived from *str*.
|
|
261
|
-
|
|
262
|
-
```js
|
|
263
|
-
const koffi = require('koffi');
|
|
264
|
-
const lib = koffi.load('libc.so.6');
|
|
265
|
-
|
|
266
|
-
// You can also use: const strdup = lib.func('const char *! strdup(const char *str)')
|
|
267
|
-
const HeapStr = koffi.disposable('str');
|
|
268
|
-
const strdup = lib.cdecl('strdup', HeapStr, ['str']);
|
|
269
|
-
|
|
270
|
-
let copy = strdup('Hello!');
|
|
271
|
-
console.log(copy); // Prints Hello!
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
When you declare functions with the [prototype-like syntax](#c-like-prototypes), you can either use named disposable types or use the '!' shortcut qualifier with compatibles types, as shown in the example below. This qualifier creates an anonymous disposable type that calls `koffi.free(ptr)`.
|
|
275
|
-
|
|
276
|
-
```js
|
|
277
|
-
const koffi = require('koffi');
|
|
278
|
-
const lib = koffi.load('libc.so.6');
|
|
279
|
-
|
|
280
|
-
// You can also use: const strdup = lib.func('const char *! strdup(const char *str)')
|
|
281
|
-
const strdup = lib.func('str! strdup(const char *str)');
|
|
282
|
-
|
|
283
|
-
let copy = strdup('World!');
|
|
284
|
-
console.log(copy); // Prints World!
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
Disposable types can only be created from pointer or string types.
|
|
288
|
-
|
|
289
|
-
```{warning}
|
|
290
|
-
Be careful on Windows: if your shared library uses a different CRT (such as msvcrt), the memory could have been allocated by a different malloc/free implementation or heap, resulting in undefined behavior if you use `koffi.free()`.
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Javascript callbacks
|
|
294
|
-
|
|
295
|
-
In order to pass a JS function to a C function expecting a callback, you must first create a callback type with the expected return type and parameters. The syntax is similar to the one used to load functions from a shared library.
|
|
296
|
-
|
|
297
|
-
```js
|
|
298
|
-
const koffi = require('koffi');
|
|
299
|
-
|
|
300
|
-
// With the classic syntax, this callback expects an integer and returns nothing
|
|
301
|
-
const ExampleCallback = koffi.callback('ExampleCallback', 'void', ['int']);
|
|
302
|
-
|
|
303
|
-
// With the prototype parser, this callback expects a double and float, and returns the sum as a double
|
|
304
|
-
const AddDoubleFloat = koffi.callback('double AddDoubleFloat(double d, float f)');
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
Once your callback type is declared, you can use a pointer to it in struct definitions, or as function parameters and/or return types.
|
|
308
|
-
|
|
309
|
-
```{note}
|
|
310
|
-
Callbacks **have changed in version 2.0**.
|
|
311
|
-
|
|
312
|
-
In Koffi 1.x, callbacks were defined in a way that made them usable directly as parameter and return types, obscuring the underlying pointer.
|
|
313
|
-
|
|
314
|
-
Now, you must use them through a pointer: `void CallIt(CallbackType func)` in Koffi 1.x becomes `void CallIt(CallbackType *func)` in version 2.0 and newer.
|
|
315
|
-
|
|
316
|
-
Consult the [migration guide](changes.md) for more information.
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
Koffi only uses predefined static trampolines, and does not need to generate code at runtime, which makes it compatible with platforms with hardened W^X migitations (such as PaX mprotect). However, this imposes some restrictions on the maximum number of callbacks, and their duration.
|
|
320
|
-
|
|
321
|
-
Thus, Koffi distinguishes two callback modes:
|
|
322
|
-
|
|
323
|
-
- [Transient callbacks](#transient-callbacks) can only be called while the C function they are passed to is running, and are invalidated when it returns. If the C function calls the callback later, the behavior is undefined, though Koffi tries to detect such cases. If it does, an exception will be thrown, but this is no guaranteed. However, they are simple to use, and don't require any special handling.
|
|
324
|
-
- [Registered callbacks](#registered-callbacks) can be called at any time, but they must be manually registered and unregistered. A limited number of registered callbacks can exist at the same time.
|
|
325
|
-
|
|
326
|
-
You need to specify the correct [calling convention](#calling-conventions) on x86 platforms, or the behavior is undefined (Node will probably crash). Only *cdecl* and *stdcall* callbacks are supported.
|
|
327
|
-
|
|
328
|
-
### Transient callbacks
|
|
329
|
-
|
|
330
|
-
Use transient callbacks when the native C function only needs to call them while it runs (e.g. qsort, progress callback, `sqlite3_exec`). Here is a small example with the C part and the JS part.
|
|
331
|
-
|
|
332
|
-
```c
|
|
333
|
-
#include <string.h>
|
|
334
|
-
|
|
335
|
-
int TransferToJS(const char *name, int age, int (*cb)(const char *str, int age))
|
|
336
|
-
{
|
|
337
|
-
char buf[64];
|
|
338
|
-
snprintf(buf, sizeof(buf), "Hello %s!", str);
|
|
339
|
-
return cb(buf, age);
|
|
340
|
-
}
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
```js
|
|
344
|
-
const koffi = require('koffi');
|
|
345
|
-
const lib = koffi.load('./callbacks.so'); // Fake path
|
|
346
|
-
|
|
347
|
-
const TransferCallback = koffi.callback('int TransferCallback(const char *str, int age)');
|
|
348
|
-
|
|
349
|
-
const TransferToJS = lib.func('TransferToJS', 'int', ['str', 'int', koffi.pointer(TransferCallback)]);
|
|
350
|
-
|
|
351
|
-
let ret = TransferToJS('Niels', 27, (str, age) => {
|
|
352
|
-
console.log(str);
|
|
353
|
-
console.log('Your age is:', age);
|
|
354
|
-
return 42;
|
|
355
|
-
});
|
|
356
|
-
console.log(ret);
|
|
357
|
-
|
|
358
|
-
// This example prints:
|
|
359
|
-
// Hello Niels!
|
|
360
|
-
// Your age is: 27
|
|
361
|
-
// 42
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### Registered callbacks
|
|
365
|
-
|
|
366
|
-
*New in Koffi 2.0*
|
|
367
|
-
|
|
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.
|
|
369
|
-
|
|
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.
|
|
371
|
-
|
|
372
|
-
The example below shows how to register and unregister delayed callbacks.
|
|
373
|
-
|
|
374
|
-
```c
|
|
375
|
-
static const char *(*g_cb1)(const char *name);
|
|
376
|
-
static void (*g_cb2)(const char *str);
|
|
377
|
-
|
|
378
|
-
void RegisterFunctions(const char *(*cb1)(const char *name), void (*cb2)(const char *str))
|
|
379
|
-
{
|
|
380
|
-
g_cb1 = cb1;
|
|
381
|
-
g_cb2 = cb2;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
void SayIt(const char *name)
|
|
385
|
-
{
|
|
386
|
-
const char *str = g_cb1(name);
|
|
387
|
-
g_cb2(str);
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
```js
|
|
392
|
-
const koffi = require('koffi');
|
|
393
|
-
const lib = koffi.load('./callbacks.so'); // Fake path
|
|
394
|
-
|
|
395
|
-
const GetCallback = koffi.callback('const char *GetCallback(const char *name)');
|
|
396
|
-
const PrintCallback = koffi.callback('void PrintCallback(const char *str)');
|
|
397
|
-
|
|
398
|
-
const RegisterFunctions = lib.func('void RegisterFunctions(GetCallback *cb1, PrintCallback *cb2)');
|
|
399
|
-
const SayIt = lib.func('void SayIt(const char *name)');
|
|
400
|
-
|
|
401
|
-
let cb1 = koffi.register(name => 'Hello ' + name + '!', koffi.pointer(GetCallback));
|
|
402
|
-
let cb2 = koffi.register(console.log, 'PrintCallback *');
|
|
403
|
-
|
|
404
|
-
RegisterFunctions(cb1, cb2);
|
|
405
|
-
SayIt('Kyoto'); // Prints Hello Kyoto!
|
|
406
|
-
|
|
407
|
-
koffi.unregister(cb1);
|
|
408
|
-
koffi.unregister(cb2);
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
### Handling of exceptions
|
|
412
|
-
|
|
413
|
-
If an exception happens inside the JS callback, the C API will receive 0 or NULL (depending on the return value type).
|
|
414
|
-
|
|
415
|
-
Handle the exception yourself (with try/catch) if you need to handle exceptions differently.
|
|
416
|
-
|
|
417
|
-
## Thread safety
|
|
418
|
-
|
|
419
|
-
Asynchronous functions run on worker threads. You need to deal with thread safety issues if you share data between threads.
|
|
420
|
-
|
|
421
|
-
Callbacks must be called from the main thread, or more precisely from the same thread as the V8 intepreter. Calling a callback from another thread is undefined behavior, and will likely lead to a crash or a big mess. You've been warned!
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
Koffi |version|
|
|
2
|
-
===============
|
|
3
|
-
|
|
4
|
-
Overview
|
|
5
|
-
--------
|
|
6
|
-
|
|
7
|
-
Koffi is a **fast and easy-to-use C FFI module for Node.js**, featuring:
|
|
8
|
-
|
|
9
|
-
* Low-overhead and fast performance (see :ref:`benchmarks<Benchmarks>`)
|
|
10
|
-
* Support for primitive and aggregate data types (structs and fixed-size arrays), both by reference (pointer) and by value
|
|
11
|
-
* Javascript functions can be used as C callbacks (since 1.2.0)
|
|
12
|
-
* Well-tested code base for :ref:`popular OS/architecture combinations<Supported platforms>`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Koffi requires a recent `Node.js <https://nodejs.org/>`_ version with N-API version 8 support, see :ref:`this page<Node.js>` for more information.
|
|
16
|
-
|
|
17
|
-
The source code is available here: https://github.com/Koromix/luigi/ (in the *koffi* subdirectory).
|
|
18
|
-
|
|
19
|
-
Table of contents
|
|
20
|
-
-----------------
|
|
21
|
-
|
|
22
|
-
.. toctree::
|
|
23
|
-
:maxdepth: 2
|
|
24
|
-
|
|
25
|
-
platforms
|
|
26
|
-
start
|
|
27
|
-
types
|
|
28
|
-
functions
|
|
29
|
-
memory
|
|
30
|
-
benchmarks
|
|
31
|
-
contribute
|
|
32
|
-
changes
|
|
33
|
-
|
|
34
|
-
License
|
|
35
|
-
-------
|
|
36
|
-
|
|
37
|
-
This program is free software: you can redistribute it and/or modify it under the terms of the **GNU Affero General Public License** as published by the Free Software Foundation, either **version 3 of the License**, or (at your option) any later version.
|
|
38
|
-
|
|
39
|
-
Find more information here: https://www.gnu.org/licenses/
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Memory usage
|
|
2
|
-
|
|
3
|
-
## How it works
|
|
4
|
-
|
|
5
|
-
For synchronous/normal calls, Koffi uses two preallocated memory blocks:
|
|
6
|
-
|
|
7
|
-
- One to construct the C stack and assign registers, subsequently used by the platform-specific assembly code (1 MiB by default)
|
|
8
|
-
- One to allocate strings and big objects/structs (2 MiB by default)
|
|
9
|
-
|
|
10
|
-
Unless very big strings or objects (at least more than one page of memory) are used, Koffi does not directly allocate any extra memory during calls or callbacks. However, please note that the JS engine (V8) might.
|
|
11
|
-
|
|
12
|
-
The size (in bytes) of these preallocated blocks can be changed. Use `koffi.config()` to get an object with the settings, and `koffi.config(obj)` to apply new settings.
|
|
13
|
-
|
|
14
|
-
```js
|
|
15
|
-
let config = koffi.config();
|
|
16
|
-
console.log(config);
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
The same is true for asynchronous calls. When an asynchronous call is made, Koffi will allocate new blocks unless there is an unused (resident) set of blocks still available. Once the asynchronous call is finished, these blocks are freed if there are more than `resident_async_pools` sets of blocks left around.
|
|
20
|
-
|
|
21
|
-
There cannot be more than `max_async_calls` running at the same time.
|
|
22
|
-
|
|
23
|
-
## Default settings
|
|
24
|
-
|
|
25
|
-
Setting | Default | Description
|
|
26
|
-
-------------------- | ------- | -----------------------------------------------
|
|
27
|
-
sync_stack_size | 1 MiB | Stack size for synchronous calls
|
|
28
|
-
sync_heap_size | 2 MiB | Heap size for synchronous calls
|
|
29
|
-
async_stack_size | 256 kiB | Stack size for asynchronous calls
|
|
30
|
-
async_heap_size | 512 kiB | Heap size for asynchronous calls
|
|
31
|
-
resident_async_pools | 2 | Number of resident pools for asynchronous calls
|
|
32
|
-
max_async_calls | 64 | Maximum number of ongoing asynchronous calls
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Requirements
|
|
2
|
-
|
|
3
|
-
## Node.js
|
|
4
|
-
|
|
5
|
-
Koffi requires a recent [Node.js](https://nodejs.org/) version with [N-API](https://nodejs.org/api/n-api.html) version 8 support:
|
|
6
|
-
|
|
7
|
-
- Node < 12.22.0 is not supported
|
|
8
|
-
- _Node 12.x_: Node 12.22.0 or newer
|
|
9
|
-
- _Node 14.x_: Node 14.17.0 or newer
|
|
10
|
-
- _Node 15.x_: Node 15.12.0 or newer
|
|
11
|
-
- Node 16.0.0 or later versions
|
|
12
|
-
|
|
13
|
-
Use [NVM](https://github.com/nvm-sh/nvm) to install more recent Node versions on older Linux distributions.
|
|
14
|
-
|
|
15
|
-
## Supported platforms
|
|
16
|
-
|
|
17
|
-
The following combinations of OS and architectures __are officially supported and tested__ at the moment:
|
|
18
|
-
|
|
19
|
-
ISA / OS | Windows | Linux | macOS | FreeBSD | OpenBSD
|
|
20
|
-
------------------ | ----------- | -------- | ----------- | ----------- | --------
|
|
21
|
-
x86 (IA32) [^1] | ✅ Yes | ✅ Yes | ⬜️ *N/A* | ✅ Yes | ✅ Yes
|
|
22
|
-
x86_64 (AMD64) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes
|
|
23
|
-
ARM32 LE [^2] | ⬜️ *N/A* | ✅ Yes | ⬜️ *N/A* | 🟨 Probably | 🟨 Probably
|
|
24
|
-
ARM64 (AArch64) LE | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | 🟨 Probably
|
|
25
|
-
RISC-V 64 [^3] | ⬜️ *N/A* | ✅ Yes | ⬜️ *N/A* | 🟨 Probably | 🟨 Probably
|
|
26
|
-
|
|
27
|
-
[^1]: The following call conventions are supported for forward calls: cdecl, stdcall, MS fastcall, thiscall. Only cdecl and stdcall can be used for C to JS callbacks.
|
|
28
|
-
[^2]: The prebuilt binary uses the hard float ABI and expects a VFP coprocessor. Build from source to use Koffi with a different ABI (softfp, soft).
|
|
29
|
-
[^3]: The prebuilt binary uses the LP64D (double-precision float) ABI. The LP64 ABI is supported in theory if you build Koffi from source (untested), the LP64F ABI is not supported.
|
|
30
|
-
|
|
31
|
-
For all fully supported platforms (green check marks), a prebuilt binary is included in the NPM package which means you can install Koffi without a C++ compiler.
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Quick start
|
|
2
|
-
|
|
3
|
-
## Install Koffi
|
|
4
|
-
|
|
5
|
-
You can install Koffi with npm:
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
npm install koffi
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Once you have installed Koffi, you can start by loading it this way:
|
|
12
|
-
|
|
13
|
-
```js
|
|
14
|
-
const koffi = require('koffi');
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Below you can find three examples:
|
|
18
|
-
|
|
19
|
-
* The first one runs on Linux. The functions are declared with the C-like prototype language.
|
|
20
|
-
* The second one runs on Windows, and uses the node-ffi like syntax to declare functions.
|
|
21
|
-
|
|
22
|
-
## Small Linux example
|
|
23
|
-
|
|
24
|
-
This is a small example for Linux systems, which uses `gettimeofday()`, `localtime_r()` and `printf()` to print the current time.
|
|
25
|
-
|
|
26
|
-
It illustrates the use of output parameters.
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
const koffi = require('koffi');
|
|
30
|
-
|
|
31
|
-
// Load the shared library
|
|
32
|
-
const lib = koffi.load('libc.so.6');
|
|
33
|
-
|
|
34
|
-
// Declare struct types
|
|
35
|
-
const timeval = koffi.struct('timeval', {
|
|
36
|
-
tv_sec: 'unsigned int',
|
|
37
|
-
tv_usec: 'unsigned int'
|
|
38
|
-
});
|
|
39
|
-
const timezone = koffi.struct('timezone', {
|
|
40
|
-
tz_minuteswest: 'int',
|
|
41
|
-
tz_dsttime: 'int'
|
|
42
|
-
});
|
|
43
|
-
const time_t = koffi.struct('time_t', { value: 'int64_t' });
|
|
44
|
-
const tm = koffi.struct('tm', {
|
|
45
|
-
tm_sec: 'int',
|
|
46
|
-
tm_min: 'int',
|
|
47
|
-
tm_hour: 'int',
|
|
48
|
-
tm_mday: 'int',
|
|
49
|
-
tm_mon: 'int',
|
|
50
|
-
tm_year: 'int',
|
|
51
|
-
tm_wday: 'int',
|
|
52
|
-
tm_yday: 'int',
|
|
53
|
-
tm_isdst: 'int'
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Find functions
|
|
57
|
-
const gettimeofday = lib.func('int gettimeofday(_Out_ timeval *tv, _Out_ timezone *tz)');
|
|
58
|
-
const localtime_r = lib.func('tm *localtime_r(const time_t *timeval, _Out_ tm *result)');
|
|
59
|
-
const printf = lib.func('int printf(const char *format, ...)');
|
|
60
|
-
|
|
61
|
-
// Get local time
|
|
62
|
-
let tv = {};
|
|
63
|
-
let now = {};
|
|
64
|
-
gettimeofday(tv, null);
|
|
65
|
-
localtime_r({ value: tv.tv_sec }, now);
|
|
66
|
-
|
|
67
|
-
// And format it with printf (variadic function)
|
|
68
|
-
printf('Hello World!\n');
|
|
69
|
-
printf('Local time: %02d:%02d:%02d\n', 'int', now.tm_hour, 'int', now.tm_min, 'int', now.tm_sec);
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Small Windows example
|
|
73
|
-
|
|
74
|
-
This is a small example targeting the Win32 API, using `MessageBox()` to show a *Hello World!* message to the user.
|
|
75
|
-
|
|
76
|
-
It illustrates the use of the x86 stdcall calling convention, and the use of UTF-8 and UTF-16 string arguments.
|
|
77
|
-
|
|
78
|
-
```js
|
|
79
|
-
const koffi = require('koffi');
|
|
80
|
-
|
|
81
|
-
// Load the shared library
|
|
82
|
-
const lib = koffi.load('user32.dll');
|
|
83
|
-
|
|
84
|
-
// Declare constants
|
|
85
|
-
const MB_OK = 0x0;
|
|
86
|
-
const MB_YESNO = 0x4;
|
|
87
|
-
const MB_ICONQUESTION = 0x20;
|
|
88
|
-
const MB_ICONINFORMATION = 0x40;
|
|
89
|
-
const IDOK = 1;
|
|
90
|
-
const IDYES = 6;
|
|
91
|
-
const IDNO = 7;
|
|
92
|
-
|
|
93
|
-
// Find functions
|
|
94
|
-
const MessageBoxA = lib.stdcall('MessageBoxA', 'int', ['void *', 'str', 'str', 'uint']);
|
|
95
|
-
const MessageBoxW = lib.stdcall('MessageBoxW', 'int', ['void *', 'str16', 'str16', 'uint']);
|
|
96
|
-
|
|
97
|
-
let ret = MessageBoxA(null, 'Do you want another message box?', 'Koffi', MB_YESNO | MB_ICONQUESTION);
|
|
98
|
-
if (ret == IDYES)
|
|
99
|
-
MessageBoxW(null, 'Hello World!', 'Koffi', MB_ICONINFORMATION);
|
|
100
|
-
```
|