运行时检测
SenRi FFI 在模块首次加载时自动检测当前 JavaScript 运行时,并选择相应的 FFI 适配器。
检测逻辑
检测代码位于 src/index.ts,核心逻辑如下:
ts
function detectRuntime(): any {
// 1. 优先检测 KossJS
if (typeof globalThis._senri_ffi !== 'undefined' && globalThis._senri_ffi) {
return new KossJSAdapter();
}
// 2. 其次检测 Bun
if (typeof Bun !== 'undefined' && Bun.ffi) {
return new BunAdapter();
}
// 3. 最后检测 Node.js
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
return new NodeAdapter();
}
// 4. 都不匹配则抛出错误
throw new Error('Unsupported JavaScript runtime: expected KossJS, Bun (>=1.0), or Node.js (>=18)');
}检测顺序
检测按优先级从高到低进行:
1. KossJS(最高优先级)
- 检测条件:
globalThis._senri_ffi存在且为真值 - 适配器类:
KossJSAdapter - 底层 API:
globalThis._senri_ffi对象提供的方法(open、func、struct等) - 类型映射:直接使用 KossJS 原生的类型名称(
int32、float64等)
KossJS 被放在最高优先级,因为:
- KossJS 同时暴露
globalThis._senri_ffi和process.versions.node(Node.js 兼容层) - 如果不优先检测 KossJS,可能会被误判为 Node.js,从而尝试加载
koffi但失败
2. Bun
- 检测条件:
Bun全局变量存在且Bun.ffi可用 - 适配器类:
BunAdapter - 底层 API:
Bun.ffi.dlopen、Bun.ffi.Callback、Bun.ffi.ptr等 - 类型映射:
i8/u8/i16/u16/i32/u32/i64/u64/f32/f64/ptr/cstring
3. Node.js(最低优先级)
- 检测条件:
process.versions.node存在 - 适配器类:
NodeAdapter - 底层 API:
koffi(需要单独安装,懒加载) - 类型映射:
koffi.int8/koffi.uint8/.../koffi.string等
适配器初始化流程
模块 import → detectRuntime() → 创建适配器实例
↓
setCallbackAdapter(adapter)
setLibraryAdapter(adapter)
setMemoryAdapter(adapter)
↓
适配器就绪,所有 API 可用初始化在模块顶层同步执行,只执行一次。后续所有 import { ... } from 'senri_ffi' 都复用同一个适配器实例。
类型映射对照表
各运行时对统一类型名称的映射:
| 统一类型 | KossJS | Bun | Node.js (koffi) |
|---|---|---|---|
void | void | void | koffi.void |
int8 | int8 | i8 | koffi.int8 |
uint8 | uint8 | u8 | koffi.uint8 |
int16 | int16 | i16 | koffi.int16 |
uint16 | uint16 | u16 | koffi.uint16 |
int32 | int32 | i32 | koffi.int32 |
uint32 | uint32 | u32 | koffi.uint32 |
int64 | int64 | i64 | koffi.int64 |
uint64 | uint64 | u64 | koffi.uint64 |
float32 | float32 | f32 | koffi.float |
float64 | float64 | f64 | koffi.double |
pointer | pointer | ptr | koffi.pointer |
cstring | cstring | cstring | koffi.string |
用户始终使用左侧的统一类型名称,无需关心底层映射。
运行时差异
KossJS
- 内置完整的 FFI 支持
- 支持结构体定义
- 支持
errno()/strerror()系统调用 - 库句柄有
close()方法
Bun
- 内置 FFI 支持
- 结构体支持有限(
createStructType返回null) - 不支持
errno()/strerror() - 每次绑定函数都会重新
dlopen(内部有缓存机制)
Node.js
- 需要安装
koffi - 通过
Buffer.allocUnsafe分配内存 - 库生命周期由 koffi 自动管理(
closeLibrary为空操作) - 不支持
errno()/strerror()
不支持的环境
如果不在 KossJS、Bun 或 Node.js 中运行,模块导入时会抛出:
Error: Unsupported JavaScript runtime: expected KossJS, Bun (>=1.0), or Node.js (>=18)下一步:
- API 概览 - 浏览所有可用 API
- 什么是 SenRi FFI - 了解项目背景
