Since: 7.4

final class FFI (View source)

FFI class provides access to a simple way to call native functions, access native variables and create/access data structures defined in the C language.

Constants

__BIGGEST_ALIGNMENT__

Methods

static FFI
cdef(string $code = '', string|null $lib = null)

The method creates a binding on the existing C function.

static FFI|null
load(string $filename)

Instead of embedding of a long C definition into a PHP string and creating FFI through {FFI::cdef()}, it's possible to separate it into a C header file. Note that C preprocessor directives (e.g., #define or #ifdef) are not supported. And only a couple of special macros may be used, especially for FFI.

static FFI
scope(string $name)

FFI definition parsing and shared library loading may take significant time. It's not useful to do it on each HTTP request in the WEB environment. However, it's possible to preload FFI definitions and libraries at php startup, and instantiate FFI objects when necessary. Header files may be extended with FFI_SCOPE define (default preloading scope is "C"). This name is going to be used as {FFI::scope()} argument. It's possible to preload a few files into a single scope.

CData|null
new(CType|string $type, bool $owned = true, bool $persistent = false)

Method that creates an arbitrary C structure.

static void
free(CData $ptr)

Manually removes previously created "not-owned" data structure.

CData|null
cast(CType|string $type, CData|int|float|bool|null $ptr)

Creates a new {FFI\CData} object, that references the same C data structure, but is associated with a different type. The resulting object does not own the C data, and the source ptr must survive the result. The C type may be specified as a {string} with any valid C type declaration or as {FFI\CType} object, created before. Any type declared for the instance is allowed.

CType|null
type(string $type)

This function creates and returns a {FFI\CType} object for the given string containing a C type declaration. Any type declared for the instance is allowed.

static CType
typeof(CData $ptr)

This function returns the FFI\CType object, representing the type of the given {FFI\CData} object.

static CType
arrayType(CType $type, array $dimensions)

Constructs a new C array type with elements of $type and dimensions specified by $dimensions.

static CData
addr(CData $ptr)

Returns a C pointer to the given C data structure. The pointer is not "owned" and won't be free. Anyway, this is a potentially unsafe operation, because the life-time of the returned pointer may be longer than the life-time of the source object, and this may cause dangling pointer dereference (like in regular C).

static int
sizeof(CData|CType $ptr)

Returns the size of a C data type of the given {FFI\CData} or {FFI\CType}.

static int
alignof(CData|CType $ptr)

Returns the size of a C data type of the given {FFI\CData} or {FFI\CType}.

static void
memcpy(CData $to, CData|string $from, int $size)

Copies $size bytes from the memory area $from to the memory area $to.

static int
memcmp(CData|string $ptr1, CData|string $ptr2, int $size)

Compares $size bytes from the memory areas $ptr1 and $ptr2.

static void
memset(CData $ptr, int $value, int $size)

Fills $size bytes of the memory area pointed to by $ptr with the given byte $value.

static string
string(CData $ptr, int|null $size = null)

Creates a PHP string from $size bytes of the memory area pointed by $ptr. If size is omitted, $ptr must be a zero-terminated array of C chars.

static bool
isNull(CData $ptr)

Checks whether the FFI\CData is a null pointer.

Details

static FFI cdef(string $code = '', string|null $lib = null)

The method creates a binding on the existing C function.

All variables and functions defined by first arguments are bound to corresponding native symbols in a DSO library and then may be accessed as FFI object methods and properties. C types of argument, return value, and variables are automatically converted to/from PHP types (if possible). Otherwise, they are wrapped in a special CData proxy object and may be accessed by elements.

Parameters

string $code

A string containing a sequence of declarations in regular C language (types, structures, functions, variables, etc). Actually, this string may be copy-pasted from C header files.

Note: C preprocessor directives are not supported, i.e. #include, #define and CPP macros do not work.

string|null $lib

The name of a shared library file, to be loaded and linked with the definitions.

Note: If lib is omitted or {\null}, platforms supporting RTLD_DEFAULT attempt to lookup symbols declared in code in the normal global scope. Other systems will fail to resolve these symbols.

Return Value

FFI

Returns the freshly created FFI object.

Exceptions

ParserException

static FFI|null load(string $filename)

Instead of embedding of a long C definition into a PHP string and creating FFI through {FFI::cdef()}, it's possible to separate it into a C header file. Note that C preprocessor directives (e.g., #define or #ifdef) are not supported. And only a couple of special macros may be used, especially for FFI.

#define FFI_LIB "libc.so.6"

int printf(const char *format, ...);

Here, FFI_LIB specifies that the given library should be loaded.

$ffi = FFI::load(__DIR__ . "/printf.h");
$ffi->printf("Hello world!\n");

Parameters

string $filename

The name of a C header file. C preprocessor directives are not supported, i.e. #include, #define and CPP macros do not work, except for special cases listed below. The header file should contain a #define statement for the FFI_SCOPE variable, e.g.: #define FFI_SCOPE "MYLIB". Refer to the class introduction for details. The header file may contain a #define statement for the FFI_LIB variable to specify the library it exposes. If it is a system library only the file name is required, e.g.: #define FFI_LIB "libc.so.6". If it is a custom library, a relative path is required, e.g.: #define FFI_LIB "./mylib.so".

Return Value

FFI|null

Returns the freshly created {\FFI} object, or {\null} on failure.

static FFI scope(string $name)

FFI definition parsing and shared library loading may take significant time. It's not useful to do it on each HTTP request in the WEB environment. However, it's possible to preload FFI definitions and libraries at php startup, and instantiate FFI objects when necessary. Header files may be extended with FFI_SCOPE define (default preloading scope is "C"). This name is going to be used as {FFI::scope()} argument. It's possible to preload a few files into a single scope.

#define FFI_LIB "libc.so.6"
#define FFI_SCOPE "libc"

int printf(const char *format, ...);

These files are loaded through the same FFI::load() load function, executed from a file loaded by opcache.preload in the php.ini directive.

ffi.preload=/etc/php/ffi/printf.h

Finally, FFI::scope() instantiates an FFI object that implements all C definitions from the given scope.

$ffi = FFI::scope("libc");
$ffi->printf("Hello world!\n");

Parameters

string $name

The scope name defined by a special FFI_SCOPE define.

Return Value

FFI

Returns the freshly created {\FFI} object.

CData|null new(CType|string $type, bool $owned = true, bool $persistent = false)

Method that creates an arbitrary C structure.

Creates a native data structure of the given C type. Any type declared for the instance is allowed.

Note: Calling {\FFI::new()} statically is deprecated since PHP 8.3.

Parameters

CType|string $type

is a valid C declaration as {\string}, or an instance of {\FFI\CType} which has already been created.

bool $owned

Whether to create owned (i.e. managed) or unmanaged data. Managed data lives together with the returned {\FFI\CData} object, and is released when the last reference to that object is released by regular PHP reference counting or GC. Unmanaged data should be released by calling {\FFI::free()}, when no longer needed.

bool $persistent

Whether to allocate the C data structure permanently on the system heap (using malloc()), or on the PHP request heap (using emalloc()).

Return Value

CData|null

Returns the freshly created {\FFI\CData} object, or {\null} on failure.

Exceptions

ParserException

static void free(CData $ptr)

Manually removes previously created "not-owned" data structure.

Parameters

CData $ptr

The handle of the unmanaged pointer to a C data structure.

Return Value

void

CData|null cast(CType|string $type, CData|int|float|bool|null $ptr)

Creates a new {FFI\CData} object, that references the same C data structure, but is associated with a different type. The resulting object does not own the C data, and the source ptr must survive the result. The C type may be specified as a {string} with any valid C type declaration or as {FFI\CType} object, created before. Any type declared for the instance is allowed.

Note: Calling {\FFI::cast()} statically is deprecated since PHP 8.3.

$ffi = FFI::cdef();

$int32Value = $ffi->new('int32_t');
$int16Array = $ffi->cast('int16_t[2]', $int32Value);

Parameters

CType|string $type

A valid C declaration as {\string}, or an instance of {\FFI\CType} which has already been created.

CData|int|float|bool|null $ptr

The handle of the pointer to a C data structure.

Return Value

CData|null

Returns the freshly created {\FFI\CData} object.

CType|null type(string $type)

This function creates and returns a {FFI\CType} object for the given string containing a C type declaration. Any type declared for the instance is allowed.

$ffi = FFI::cdef();

$type = $ffi->type('int[2][3]');

Parameters

string $type

A valid C declaration as {\string}.

Return Value

CType|null

Returns the freshly created {\FFI\CType} object, or {\null} on failure.

static CType typeof(CData $ptr)

This function returns the FFI\CType object, representing the type of the given {FFI\CData} object.

Parameters

CData $ptr

The handle of the pointer to a C data structure.

Return Value

CType

Returns the {\FFI\CType} object representing the type of the given {\FFI\CData} object.

static CType arrayType(CType $type, array $dimensions)

Constructs a new C array type with elements of $type and dimensions specified by $dimensions.

$ffi = FFI::cdef();

$t1 = $ffi->type('int[2][3]');
$t2 = FFI::arrayType($ffi->type('int'), [2, 3]);

Parameters

CType $type

A valid C declaration as string, or an instance of {\FFI\CType} which has already been created.

array $dimensions

The dimensions of the type as {\array}.

Return Value

CType

Returns the freshly created {\FFI\CType} object.

static CData addr(CData $ptr)

Returns a C pointer to the given C data structure. The pointer is not "owned" and won't be free. Anyway, this is a potentially unsafe operation, because the life-time of the returned pointer may be longer than the life-time of the source object, and this may cause dangling pointer dereference (like in regular C).

Parameters

CData $ptr

The handle of the pointer to a C data structure.

Return Value

CData

Returns the freshly created {\FFI\CData} object.

static int sizeof(CData|CType $ptr)

Returns the size of a C data type of the given {FFI\CData} or {FFI\CType}.

Parameters

CData|CType $ptr

The handle of the C data or type.

Return Value

int

The size of the memory area pointed at by ptr.

static int alignof(CData|CType $ptr)

Returns the size of a C data type of the given {FFI\CData} or {FFI\CType}.

Parameters

CData|CType $ptr

The handle of the C data or type.

Return Value

int

Returns the alignment of the given {\FFI\CData} or {\FFI\CType} object.

static void memcpy(CData $to, CData|string $from, int $size)

Copies $size bytes from the memory area $from to the memory area $to.

Parameters

CData $to

The start of the memory area to copy to.

CData|string $from

The start of the memory area to copy from.

int $size

The number of bytes to copy.

Return Value

void

static int memcmp(CData|string $ptr1, CData|string $ptr2, int $size)

Compares $size bytes from the memory areas $ptr1 and $ptr2.

Both $ptr1 and $ptr2 can be any native data structures ({\FFI\CData}) or PHP strings.

Parameters

CData|string $ptr1

The start of one memory area.

CData|string $ptr2

The start of another memory area.

int $size

The number of bytes to compare.

Return Value

int

Returns a value less than 0 if the contents of the memory area starting at $ptr1 are considered less than the contents of the memory area starting at $ptr2, a value greater than 0 if the contents of the first memory area are considered greater than the second, and 0 if they are equal.

static void memset(CData $ptr, int $value, int $size)

Fills $size bytes of the memory area pointed to by $ptr with the given byte $value.

Parameters

CData $ptr

The start of the memory area to fill.

int $value

The byte to fill with.

int $size

The number of bytes to fill.

Return Value

void

static string string(CData $ptr, int|null $size = null)

Creates a PHP string from $size bytes of the memory area pointed by $ptr. If size is omitted, $ptr must be a zero-terminated array of C chars.

Parameters

CData $ptr

The start of the memory area from which to create a PHP {\string}.

int|null $size

The number of bytes to copy to the PHP {\string}. If $size is omitted or {\null}, $ptr must be a zero-terminated ("\0") array of C char.

Return Value

string

The freshly created PHP {\string}.

static bool isNull(CData $ptr)

Checks whether the FFI\CData is a null pointer.

Parameters

CData $ptr

The handle of the pointer to a C data structure.

Return Value

bool

Returns whether a {\FFI\CData} is a null pointer.