Number types

While the C standard allows for variation in the size of most integer types, Koffi enforces the same definition for most primitive types, listed below:

C type JS type Bytes Signedness Note
void Undefined 0 Only valid as a return type
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
char32, char32_t Number (integer) 4 Signed
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

Koffi also accepts BigInt values when converting from JS to C integers. If the value exceeds the range of the C type, Koffi will convert the number to an undefined value. In the reverse direction, BigInt values are automatically used when needed for big 64-bit integers.

Koffi defines a few more types that can change size depending on the OS and the architecture:

C type JS type Signedness Note
bool Boolean Usually one byte
long Number (integer) Signed 4 or 8 bytes depending on platform (LP64, LLP64)
ulong Number (integer) Unsigned 4 or 8 bytes depending on platform (LP64, LLP64)
unsigned long Number (integer) Unsigned 4 or 8 bytes depending on platform (LP64, LLP64)
intptr Number (integer) Signed 4 or 8 bytes depending on register width
intptr_t Number (integer) Signed 4 or 8 bytes depending on register width
uintptr Number (integer) Unsigned 4 or 8 bytes depending on register width
uintptr_t Number (integer) Unsigned 4 or 8 bytes depending on register width
wchar_t Number (integer) 2 bytes on Windows, 4 bytes Linux, macOS and BSD

Primitive types can be specified by name (in a string) or through koffi.types:

// These two lines do the same:
let struct1 = koffi.struct({ dummy: 'long' });
let struct2 = koffi.struct({ dummy: koffi.types.long });

String types

Koffi can convert JS strings to and from UTF-8, UTF-16 or UTF-32.

Type name Aliases JS type Conversion / encoding
const char *, char * str, string String UTF-8
const char16_t *, char16_t * str16, string16 String UTF-16
const char32_t *, char32_t * str32, string32 String UTF-32

Koffi also supports wide strings (wchar_t * or wstring), which use:

Enum types

New in Koffi 3.0

C enumeration values are stored as integers. The underlying integer type is implementation-defined but Koffi tries to match usual platform behavior.

On POSIX platforms, Koffi follows the following rules:

On Windows, things are simpler, and int is used all the time. Koffi will throw an error if any enumeration value does not fit in a 32-bit integer.

// For OpenResult, the underlying type will be unsigned int on POSIX, int on Windows
const OpenResult = koffi.enumeration('OpenResult', {
    Success: 0,
    MissingFile: 1,
    AccessDenied: 2,
    OtherError: 3
});

// For RelativePosition, the underlying type will be int everywhere
const RelativePosition = koffi.enumeration('RelativePosition', {
    Left: -1,
    Center: 0,
    Right: 1
});

// For IntLimits, the underlying type will be int64_t on POSIX, and fail on Windows
const Int64Limits = koffi.enumeration('Int64Limits', {
    Min: -9223372036854775808n,
    Max: 9223372036854775807n
});

This behavior may not match your compiler:

Use an explicit type specifier to work around these problems, as shown below.

You can access the constants in values member of the type object.

console.log(OpenResult.values.MissingFile); // Prints 1
console.log(RelativePosition.values.Left); // Prints -1

You can specify the storage type explicitly as the last argument: koffi.enumeration(name, values, type).

// This one explictly uses int64_t as the underlying type, despite the fact that the values fit inside an int.
const ExplicitEnum = koffi.enumeration('ExplicitEnum', {
    Zero: 0,
    One: 1,
    Two: 2
}, 'int64_t');

Endian-sensitive integers

Koffi defines a bunch of endian-sensitive types, which can be used when dealing with binary data (network payloads, binary file formats, etc.).

C type Bytes Signedness Endianness
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

You can find an example that uses these types to extract information from a PNG header with transparent endian conversion.