Instead of embedding of a long C definition into 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");
*
*
* @param string $filename
* @return FFI|null
*/
public static function load(string $filename): ?FFI {}
/**
* FFI definition parsing and shared library loading may take
* significant time. It's not useful to do it on each HTTP request in
* WEB environment. However, it's possible to pre-load FFI definitions
* and libraries at php startup, and instantiate FFI objects when
* necessary. Header files may be extended with FFI_SCOPE define
* (default pre-loading scope is "C"). This name is going to be
* used as FFI::scope() argument. It's possible to pre-load 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 file loaded by opcache.preload php.ini directive.
*
*
* ffi.preload=/etc/php/ffi/printf.h
*
*
* Finally, FFI::scope() instantiate an FFI object, that implements
* all C definition from the given scope.
*
*
* $ffi = FFI::scope("libc");
* $ffi->printf("Hello world!\n");
*
*
* @param string $name
* @return FFI
*/
public static function scope(string $name): FFI {}
/**
* Method that creates an arbitrary C structure.
*
* @param string|CType $type
* @param bool $owned
* @param bool $persistent
* @return CData|null
* @throws ParserException
*/
public static function new($type, bool $owned = true, bool $persistent = false): ?CData {}
/**
* Manually removes previously created "not-owned" data structure.
*
* @param CData $ptr
* @return void
*/
public static function free(CData $ptr): void {}
/**
* Casts given $pointer to another C type, specified by C declaration
* string or FFI\CType object.
*
* This function may be called statically and use only predefined
* types, or as a method of previously created FFI object. In last
* case the first argument may reuse all type and tag names
* defined in FFI::cdef().
*
* @param CType|string $type
* @param CData|int|float|bool|null $ptr
* @return CData|null
*/
public static function cast($type, $ptr): ?CData {}
/**
* This function creates and returns a FFI\CType object, representng
* type of the given C type declaration string.
*
* FFI::type() may be called statically and use only predefined types,
* or as a method of previously created FFI object. In last case the
* first argument may reuse all type and tag names defined in
* FFI::cdef().
*
* @param string $type
* @return CType|null
*/
public static function type(string $type): ?CType {}
/**
* This function returns the FFI\CType object, representing the type of
* the given FFI\CData object.
*
* @param CData $ptr
* @return CType
*/
public static function typeof(CData $ptr): CType {}
/**
* Constructs a new C array type with elements of $type and
* dimensions specified by $dimensions.
*
* @param CType $type
* @param int[] $dimensions
* @return CType
*/
public static function arrayType(CType $type, array $dimensions): CType {}
/**
* Returns 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 life-time of the source object, and this may
* cause dangling pointer dereference (like in regular C).
*
* @param CData $ptr
* @return CData
*/
public static function addr(CData $ptr): CData {}
/**
* Returns size of C data type of the given FFI\CData or FFI\CType.
*
* @param CData|CType $ptr
* @return int
*/
public static function sizeof($ptr): int {}
/**
* Returns size of C data type of the given FFI\CData or FFI\CType.
*
* @param CData|CType $ptr
* @return int
*/
public static function alignof($ptr): int {}
/**
* Copies $size bytes from memory area $source to memory area $target.
* $source may be any native data structure (FFI\CData) or PHP string.
*
* @param CData $to
* @param CData|string $from
* @param int $size
*/
public static function memcpy(CData $to, $from, int $size): void {}
/**
* Compares $size bytes from memory area $ptr1 and $ptr2.
*
* @param CData|string $ptr1
* @param CData|string $ptr2
* @param int $size
* @return int
*/
public static function memcmp($ptr1, $ptr2, int $size): int {}
/**
* Fills the $size bytes of the memory area pointed to by $target with
* the constant byte $byte.
*
* @param CData $ptr
* @param int $value
* @param int $size
*/
public static function memset(CData $ptr, int $value, int $size): void {}
/**
* Creates a PHP string from $size bytes of memory area pointed by
* $source. If size is omitted, $source must be zero terminated
* array of C chars.
*
* @param CData $ptr
* @param int|null $size
* @return string
*/
public static function string(CData $ptr, ?int $size = null): string {}
/**
* Checks whether the FFI\CData is a null pointer.
*
* @param CData $ptr
* @return bool
*/
public static function isNull(CData $ptr): bool {}
}
}
namespace FFI {
/**
* General FFI exception.
*
* @since 7.4
*/
class Exception extends \Error {}
/**
* An exception that occurs when parsing invalid header files.
*
* @since 7.4
*/
class ParserException extends Exception {}
/**
* Proxy object that provides access to compiled structures.
*
* In the case that CData is a wrapper over a scalar, it contains an
* additional "cdata" property.
*
* @property int|float|bool|null|string|CData $cdata
*
* In the case that the CData is a wrapper over an arbitrary C structure,
* then it allows reading and writing to the fields defined by
* this structure.
*
* @method mixed __get(string $name)
* @method mixed __set(string $name, mixed $value)
*
* In the case that CData is a wrapper over an array, it is an
* implementation of the {@see \Traversable}, {@see \Countable},
* and {@see \ArrayAccess}
*
* @mixin \Traversable
* @mixin \Countable
* @mixin \ArrayAccess
*
* In the case when CData is a wrapper over a function pointer, it can
* be called.
*
* @method mixed __invoke(mixed ...$args)
*
* @since 7.4
*/
class CData
{
/**
* Note that this method does not physically exist and is only required
* for correct type inference.
*
* @param int $offset
* @return bool
*/
private function offsetExists(int $offset) {}
/**
* Note that this method does not physically exist and is only required
* for correct type inference.
*
* @param int $offset
* @return CData|int|float|bool|null|string
*/
private function offsetGet(int $offset) {}
/**
* Note that this method does not physically exist and is only required
* for correct type inference.
*
* @param int $offset
* @param CData|int|float|bool|null|string $value
*/
private function offsetSet(int $offset, $value) {}
/**
* Note that this method does not physically exist and is only required
* for correct type inference.
*
* @param int $offset
*/
private function offsetUnset(int $offset) {}
/**
* Note that this method does not physically exist and is only required
* for correct type inference.
*
* @return int
*/
private function count(): int {}
}
/**
* Class containing C type information.
*
* @since 7.4
*/
class CType
{
/**
* @since 8.1
*/
public const TYPE_VOID = 0;
/**
* @since 8.1
*/
public const TYPE_FLOAT = 1;
/**
* @since 8.1
*/
public const TYPE_DOUBLE = 2;
/**
* Please note that this constant may NOT EXIST if there is
* no long double support on the current platform.
*
* @since 8.1
*/
public const TYPE_LONGDOUBLE = 3;
/**
* @since 8.1
*/
public const TYPE_UINT8 = 4;
/**
* @since 8.1
*/
public const TYPE_SINT8 = 5;
/**
* @since 8.1
*/
public const TYPE_UINT16 = 6;
/**
* @since 8.1
*/
public const TYPE_SINT16 = 7;
/**
* @since 8.1
*/
public const TYPE_UINT32 = 8;
/**
* @since 8.1
*/
public const TYPE_SINT32 = 9;
/**
* @since 8.1
*/
public const TYPE_UINT64 = 10;
/**
* @since 8.1
*/
public const TYPE_SINT64 = 11;
/**
* @since 8.1
*/
public const TYPE_ENUM = 12;
/**
* @since 8.1
*/
public const TYPE_BOOL = 13;
/**
* @since 8.1
*/
public const TYPE_CHAR = 14;
/**
* @since 8.1
*/
public const TYPE_POINTER = 15;
/**
* @since 8.1
*/
public const TYPE_FUNC = 16;
/**
* @since 8.1
*/
public const TYPE_ARRAY = 17;
/**
* @since 8.1
*/
public const TYPE_STRUCT = 18;
/**
* @since 8.1
*/
public const ATTR_CONST = 1;
/**
* @since 8.1
*/
public const ATTR_INCOMPLETE_TAG = 2;
/**
* @since 8.1
*/
public const ATTR_VARIADIC = 4;
/**
* @since 8.1
*/
public const ATTR_INCOMPLETE_ARRAY = 8;
/**
* @since 8.1
*/
public const ATTR_VLA = 16;
/**
* @since 8.1
*/
public const ATTR_UNION = 32;
/**
* @since 8.1
*/
public const ATTR_PACKED = 64;
/**
* @since 8.1
*/
public const ATTR_MS_STRUCT = 128;
/**
* @since 8.1
*/
public const ATTR_GCC_STRUCT = 256;
/**
* @since 8.1
*/
public const ABI_DEFAULT = 0;
/**
* @since 8.1
*/
public const ABI_CDECL = 1;
/**
* @since 8.1
*/
public const ABI_FASTCALL = 2;
/**
* @since 8.1
*/
public const ABI_THISCALL = 3;
/**
* @since 8.1
*/
public const ABI_STDCALL = 4;
/**
* @since 8.1
*/
public const ABI_PASCAL = 5;
/**
* @since 8.1
*/
public const ABI_REGISTER = 6;
/**
* @since 8.1
*/
public const ABI_MS = 7;
/**
* @since 8.1
*/
public const ABI_SYSV = 8;
/**
* @since 8.1
*/
public const ABI_VECTORCALL = 9;
/**
* Returns the name of the type.
*
* @since 8.0
* @return string
*/
public function getName(): string {}
/**
* Returns the identifier of the root type.
*
* Value may be one of:
* - {@see CType::TYPE_VOID}
* - {@see CType::TYPE_FLOAT}
* - {@see CType::TYPE_DOUBLE}
* - {@see CType::TYPE_LONGDOUBLE}
* - {@see CType::TYPE_UINT8}
* - {@see CType::TYPE_SINT8}
* - {@see CType::TYPE_UINT16}
* - {@see CType::TYPE_SINT16}
* - {@see CType::TYPE_UINT32}
* - {@see CType::TYPE_SINT32}
* - {@see CType::TYPE_UINT64}
* - {@see CType::TYPE_SINT64}
* - {@see CType::TYPE_ENUM}
* - {@see CType::TYPE_BOOL}
* - {@see CType::TYPE_CHAR}
* - {@see CType::TYPE_POINTER}
* - {@see CType::TYPE_FUNC}
* - {@see CType::TYPE_ARRAY}
* - {@see CType::TYPE_STRUCT}
*
* @since 8.1
* @return int
*/
public function getKind(): int {}
/**
* Returns the size of the type in bytes.
*
* @since 8.1
* @return int
*/
public function getSize(): int {}
/**
* Returns the alignment of the type in bytes.
*
* @since 8.1
* @return int
*/
public function getAlignment(): int {}
/**
* Returns the bit-mask of type attributes.
*
* @since 8.1
* @return int
*/
public function getAttributes(): int {}
/**
* Returns the identifier of the enum value type.
*
* Value may be one of:
* - {@see CType::TYPE_UINT32}
* - {@see CType::TYPE_UINT64}
*
* @since 8.1
* @return int
* @throws Exception In the case that the type is not an enumeration.
*/
public function getEnumKind(): int {}
/**
* Returns the type of array elements.
*
* @since 8.1
* @return CType
* @throws Exception In the case that the type is not an array.
*/
public function getArrayElementType(): CType {}
/**
* Returns the size of an array.
*
* @since 8.1
* @return int
* @throws Exception In the case that the type is not an array.
*/
public function getArrayLength(): int {}
/**
* Returns the original type of the pointer.
*
* @since 8.1
* @return CType
* @throws Exception In the case that the type is not a pointer.
*/
public function getPointerType(): CType {}
/**
* Returns the field string names of a structure or union.
*
* @since 8.1
* @return array