输入参数
原始类型
标准类型
虽然 C 标准允许大多数整数类型的大小存在变化,但 Koffi 对大多数基本类型强制执行相同的定义,如下所示:
void
Undefined
0
仅作为返回类型有效
int8, int8_t
Number (integer)
1
Signed
uint8, uint8_t
Number (integer)
1
Unsigned
char
Number (integer)
1
Signed
uchar, unsigned char
Number (integer)
1
Unsigned
char16, char16_t
Number (integer)
2
Signed
int16, int16_t
Number (integer)
2
Signed
uint16, uint16_t
Number (integer)
2
Unsigned
short
Number (integer)
2
Signed
ushort, unsigned short
Number (integer)
2
Unsigned
int32, int32_t
Number (integer)
4
Signed
uint32, uint32_t
Number (integer)
4
Unsigned
int
Number (integer)
4
Signed
uint, unsigned int
Number (integer)
4
Unsigned
int64, int64_t
Number (integer)
8
Signed
uint64, uint64_t
Number (integer)
8
Unsigned
longlong, long long
Number (integer)
8
Signed
ulonglong, unsigned long long
Number (integer)
8
Unsigned
float32
Number (float)
4
float64
Number (float)
8
float
Number (float)
4
double
Number (float)
8
从 JS 整数转换为 C 整数时,Koffi 还接受 BigInt 值。如果该值超出了 C 类型的范围,Koffi 会将数字转换为未定义的值。相反,当需要 64 位大整数时,会自动使用 BigInt 值。
Koffi 定义了更多类型,可以根据操作系统和架构改变大小:
bool
Boolean
通常为一个字节
long
Number (integer)
Signed
4 或 8 个字节,具体取决于平台(LP64、LLP64)
ulong
Number (integer)
Unsigned
4 或 8 个字节,具体取决于平台(LP64、LLP64)
unsigned long
Number (integer)
Unsigned
4 或 8 个字节,具体取决于平台(LP64、LLP64)
intptr
Number (integer)
Signed
4 或 8 个字节,具体取决于寄存器宽度
intptr_t
Number (integer)
Signed
4 或 8 个字节,具体取决于寄存器宽度
uintptr
Number (integer)
Unsigned
4 或 8 个字节,具体取决于寄存器宽度
uintptr_t
Number (integer)
Unsigned
4 或 8 个字节,具体取决于寄存器宽度
str, string
String
JS 字符串与 UTF-8 相互转换
str16, string16
String
JS 字符串与 UTF-16 (LE) 相互转换
基元类型可以通过名称(在字符串中)或通过以下方式指定koffi.types
字节序敏感的整数(大小端存储)
Koffi 2.1 中的新功能
Koffi 定义了一堆字节序敏感类型,可以在处理二进制数据(网络负载、二进制文件格式等)时使用。
int16_le, int16_le_t
2
Signed
Little Endian
int16_be, int16_be_t
2
Signed
Big Endian
uint16_le, uint16_le_t
2
Unsigned
Little Endian
uint16_be, uint16_be_t
2
Unsigned
Big Endian
int32_le, int32_le_t
4
Signed
Little Endian
int32_be, int32_be_t
4
Signed
Big Endian
uint32_le, uint32_le_t
4
Unsigned
Little Endian
uint32_be, uint32_be_t
4
Unsigned
Big Endian
int64_le, int64_le_t
8
Signed
Little Endian
int64_be, int64_be_t
8
Signed
Big Endian
uint64_le, uint64_le_t
8
Unsigned
Little Endian
uint64_be, uint64_be_t
8
Unsigned
Big Endian
结构类型
结构体定义
Koffi 将 JS 对象转换为 C 结构,反之亦然。
与函数声明不同,到目前为止,只有一种方法可以使用函数创建结构类型koffi.struct()
。该函数有两个参数:第一个是类型的名称,第二个是包含结构成员名称和类型的对象。您可以省略第一个参数来声明匿名结构。
以下示例说明了如何使用 Koffi 在 C 和 JS 中声明相同的结构:
Koffi 在对齐和填充方面自动遵循平台 C ABI。但是,如果需要,您可以通过以下方式覆盖这些规则:
koffi.pack()
打包所有成员,不使用(而不是koffi.struct()
)填充更改特定成员的对齐方式,如下所示
声明结构后,您可以通过名称(使用字符串,就像对基本类型所做的那样)或通过调用返回的值来使用它koffi.struct()
。声明匿名结构时,只有后者是可能的。
不透明类型
许多 C 库使用某种面向对象的 API,带有一对专用于创建和删除对象的函数。一个明显的例子可以在 stdio.h 中找到,带有不透明FILE *
指针。您可以使用fopen()
和fclose()
打开和关闭文件,并使用其他函数(例如fread()
或 ftell()
)操作不透明指针。
在 Koffi 中,您可以使用不透明类型来管理它。使用 声明不透明类型koffi.opaque(name)
,并使用指向该类型的指针作为返回类型或某种输出参数(使用双指针)。
下面的完整示例在 C 中实现了迭代字符串生成器(连接器),并从 Javascript 使用它来输出 Hello World 和 FizzBuzz 的混合内容。构建器隐藏在不透明类型后面,并使用一对 C 函数创建和销毁:ConcatNew
(or ConcatNewOut
) 和ConcatFree
。
数组类型
固定大小的 C 数组
固定大小的数组用koffi.array(type, length)
声明。就像在 C 中一样,它们不能作为函数参数传递(它们退化为指针),也不能按值返回。但是,您可以将它们嵌入到结构类型中。
在将数组传入/传出 C 时,Koffi 应用以下转换规则:
JS 到 C:Koffi 可以采用普通数组(例如
[1,2]
)或正确类型的 TypedArray(e.g.Uint8Array
for an array ofuint8_t
numbers)C 到 JS(返回值、输出参数、回调):如果可能,Koffi 将使用 TypedArray。但是,当您使用可选的提示参数创建数组类型时,您可以更改此行为:
koffi.array('uint8_t', 64, 'Array')
。对于非数字类型,例如字符串或结构数组,Koffi 创建普通数组。
请参阅下面的示例:
固定大小的字符串缓冲区
Koffi还可以在以下情况下将JS字符串转换为固定大小的数组:
char 数组用 UTF-8 编码的字符串填充,如果需要的话会被截断。缓冲区始终以 NUL 结尾。
char16(或 char16_t)数组用 UTF-16 编码的字符串填充,如果需要的话会被截断。缓冲区始终以 NUL 结尾。
反之亦然,Koffi 可以将 C 固定大小缓冲区转换为 JS 字符串。String
对于 char、char16 和 char16_t 数组,默认情况下会发生这种情况,但您也可以使用数组提示(例如koffi.array('char', 8, 'String')
)显式请求此情况。
动态数组(指针)
在 C 中,动态大小的数组通常作为指针传递。在相关部分中阅读有关数组指针的更多信息。
联合类型
联合类型的声明和使用将在后面的章节中解释,这里仅在需要时简单提及。
Last updated