diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 4e30ec577144c..50c898ad4de75 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4469,6 +4469,318 @@ ZEND_METHOD(FFI_CType, getName) /* {{{ */ RETURN_STR(res); } } +/* }}} */ + +ZEND_METHOD(FFI_CType, getKind) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + RETURN_LONG(type->kind); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getSize) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + RETURN_LONG(type->size); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getAlignment) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + RETURN_LONG(type->align); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getAttributes) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + RETURN_LONG(type->attr); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getEnumKind) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_ENUM) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not an enumeration"); + RETURN_THROWS(); + } + RETURN_LONG(type->enumeration.kind); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getArrayElementType) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + zend_ffi_ctype *ret; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_ARRAY) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not an array"); + RETURN_THROWS(); + } + + ret = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce); + ret->type = ZEND_FFI_TYPE(type->array.type); + RETURN_OBJ(&ret->std); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getArrayLength) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_ARRAY) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not an array"); + RETURN_THROWS(); + } + RETURN_LONG(type->array.length); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getPointerType) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_ctype *ret; + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_POINTER) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a pointer"); + RETURN_THROWS(); + } + + ret = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce); + ret->type = ZEND_FFI_TYPE(type->pointer.type); + RETURN_OBJ(&ret->std); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getStructFieldNames) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + HashTable *ht; + zend_string* name; + zval zv; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_STRUCT) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a structure"); + RETURN_THROWS(); + } + + ht = zend_new_array(zend_hash_num_elements(&type->record.fields)); + RETVAL_ARR(ht); + ZEND_HASH_FOREACH_STR_KEY(&type->record.fields, name) { + ZVAL_STR_COPY(&zv, name); + zend_hash_next_index_insert_new(ht, &zv); + } ZEND_HASH_FOREACH_END(); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getStructFieldOffset) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + zend_string *name; + zend_ffi_field *ptr; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(name) + ZEND_PARSE_PARAMETERS_END(); + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_STRUCT) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a structure"); + RETURN_THROWS(); + } + + ptr = zend_hash_find_ptr(&type->record.fields, name); + if (!ptr) { + zend_throw_error(zend_ffi_exception_ce, "Wrong fileld name"); + RETURN_THROWS(); + } + RETURN_LONG(ptr->offset); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getStructFieldType) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + zend_string *name; + zend_ffi_field *ptr; + zend_ffi_ctype *ret; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(name) + ZEND_PARSE_PARAMETERS_END(); + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_STRUCT) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a structure"); + RETURN_THROWS(); + } + + ptr = zend_hash_find_ptr(&type->record.fields, name); + if (!ptr) { + zend_throw_error(zend_ffi_exception_ce, "Wrong fileld name"); + RETURN_THROWS(); + } + + ret = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce); + ret->type = ZEND_FFI_TYPE(ptr->type); + RETURN_OBJ(&ret->std); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getFuncABI) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_FUNC) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a function"); + RETURN_THROWS(); + } + RETURN_LONG(type->func.abi); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getFuncReturnType) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_ctype *ret; + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_FUNC) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a function"); + RETURN_THROWS(); + } + + ret = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce); + ret->type = ZEND_FFI_TYPE(type->func.ret_type); + RETURN_OBJ(&ret->std); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getFuncArgCount) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_FUNC) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a function"); + RETURN_THROWS(); + } + RETURN_LONG(type->func.args ? zend_hash_num_elements(type->func.args) : 0); +} +/* }}} */ + +ZEND_METHOD(FFI_CType, getFuncArgType) /* {{{ */ +{ + zend_ffi_ctype *ctype = (zend_ffi_ctype*)(Z_OBJ_P(ZEND_THIS)); + zend_ffi_type *type, *ptr; + zend_long n; + zend_ffi_ctype *ret; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(n) + ZEND_PARSE_PARAMETERS_END(); + + type = ZEND_FFI_TYPE(ctype->type); + if (type->kind != ZEND_FFI_TYPE_FUNC) { + zend_throw_error(zend_ffi_exception_ce, "FFI\\CType is not a function"); + RETURN_THROWS(); + } + + if (!type->func.args) { + zend_throw_error(zend_ffi_exception_ce, "Wrong argument number"); + RETURN_THROWS(); + } + + ptr = zend_hash_index_find_ptr(type->func.args, n); + if (!ptr) { + zend_throw_error(zend_ffi_exception_ce, "Wrong argument number"); + RETURN_THROWS(); + } + + ret = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce); + ret->type = ZEND_FFI_TYPE(ptr); + RETURN_OBJ(&ret->std); +} +/* }}} */ static char *zend_ffi_parse_directives(const char *filename, char *code_pos, char **scope_name, char **lib, bool preload) /* {{{ */ { @@ -4896,6 +5208,9 @@ static int zend_ffi_preload(char *preload) /* {{{ */ } /* }}} */ +#define REGISTER_FFI_TYPE_CONSTANT(name) \ + zend_declare_class_constant_long(zend_ffi_ctype_ce, #name, sizeof(#name) - 1, ZEND_FFI_ ## name) + /* {{{ ZEND_MINIT_FUNCTION */ ZEND_MINIT_FUNCTION(ffi) { @@ -5046,6 +5361,49 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_ctype_handlers.get_properties = zend_fake_get_properties; zend_ffi_ctype_handlers.get_gc = zend_fake_get_gc; + REGISTER_FFI_TYPE_CONSTANT(TYPE_VOID); + REGISTER_FFI_TYPE_CONSTANT(TYPE_FLOAT); + REGISTER_FFI_TYPE_CONSTANT(TYPE_DOUBLE); +#ifdef HAVE_LONG_DOUBLE + REGISTER_FFI_TYPE_CONSTANT(TYPE_LONGDOUBLE); +#endif + REGISTER_FFI_TYPE_CONSTANT(TYPE_UINT8); + REGISTER_FFI_TYPE_CONSTANT(TYPE_SINT8); + REGISTER_FFI_TYPE_CONSTANT(TYPE_UINT16); + REGISTER_FFI_TYPE_CONSTANT(TYPE_SINT16); + REGISTER_FFI_TYPE_CONSTANT(TYPE_UINT32); + REGISTER_FFI_TYPE_CONSTANT(TYPE_SINT32); + REGISTER_FFI_TYPE_CONSTANT(TYPE_UINT64); + REGISTER_FFI_TYPE_CONSTANT(TYPE_SINT64); + REGISTER_FFI_TYPE_CONSTANT(TYPE_ENUM); + REGISTER_FFI_TYPE_CONSTANT(TYPE_BOOL); + REGISTER_FFI_TYPE_CONSTANT(TYPE_CHAR); + REGISTER_FFI_TYPE_CONSTANT(TYPE_POINTER); + REGISTER_FFI_TYPE_CONSTANT(TYPE_FUNC); + REGISTER_FFI_TYPE_CONSTANT(TYPE_ARRAY); + REGISTER_FFI_TYPE_CONSTANT(TYPE_STRUCT); + + REGISTER_FFI_TYPE_CONSTANT(ATTR_CONST); + REGISTER_FFI_TYPE_CONSTANT(ATTR_INCOMPLETE_TAG); + REGISTER_FFI_TYPE_CONSTANT(ATTR_VARIADIC); + REGISTER_FFI_TYPE_CONSTANT(ATTR_INCOMPLETE_ARRAY); + REGISTER_FFI_TYPE_CONSTANT(ATTR_VLA); + REGISTER_FFI_TYPE_CONSTANT(ATTR_UNION); + REGISTER_FFI_TYPE_CONSTANT(ATTR_PACKED); + REGISTER_FFI_TYPE_CONSTANT(ATTR_MS_STRUCT); + REGISTER_FFI_TYPE_CONSTANT(ATTR_GCC_STRUCT); + + REGISTER_FFI_TYPE_CONSTANT(ABI_DEFAULT); + REGISTER_FFI_TYPE_CONSTANT(ABI_CDECL); + REGISTER_FFI_TYPE_CONSTANT(ABI_FASTCALL); + REGISTER_FFI_TYPE_CONSTANT(ABI_THISCALL); + REGISTER_FFI_TYPE_CONSTANT(ABI_STDCALL); + REGISTER_FFI_TYPE_CONSTANT(ABI_PASCAL); + REGISTER_FFI_TYPE_CONSTANT(ABI_REGISTER); + REGISTER_FFI_TYPE_CONSTANT(ABI_MS); + REGISTER_FFI_TYPE_CONSTANT(ABI_SYSV); + REGISTER_FFI_TYPE_CONSTANT(ABI_VECTORCALL); + if (FFI_G(preload)) { if (zend_ffi_preload(FFI_G(preload)) != SUCCESS) { return FAILURE; diff --git a/ext/ffi/ffi.stub.php b/ext/ffi/ffi.stub.php index a6649a79d9a7e..8f20a3daa8f86 100644 --- a/ext/ffi/ffi.stub.php +++ b/ext/ffi/ffi.stub.php @@ -72,7 +72,28 @@ final class CData { } final class CType { - public function getName() : string {} + public function getName(): string {} + + public function getKind(): int {} + public function getSize(): int {} + public function getAlignment(): int {} + public function getAttributes(): int {} + + public function getEnumKind(): int {} + + public function getArrayElementType(): CType {} + public function getArrayLength(): int {} + + public function getPointerType(): CType {} + + public function getStructFieldNames(): array {} + public function getStructFieldOffset(string $field_name): int {} + public function getStructFieldType(string $field_name): CType {} + + public function getFuncABI(): int {} + public function getFuncReturnType(): CType {} + public function getFuncArgCount(): int {} + public function getFuncArgType(int $arg_index): CType {} } class Exception extends \Error { diff --git a/ext/ffi/ffi_arginfo.h b/ext/ffi/ffi_arginfo.h index 0d58573922c39..4e2c6dad06980 100644 --- a/ext/ffi/ffi_arginfo.h +++ b/ext/ffi/ffi_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e1d300639ded25533502902180fb76dd5b4d92b2 */ + * Stub hash: bdfc4211d30630290aaf5046dd4ae72936982703 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_cdef, 0, 0, FFI, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_STRING, 0, "\"\"") @@ -82,6 +82,45 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_CType_getName, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_CType_getKind, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_FFI_CType_getSize arginfo_class_FFI_CType_getKind + +#define arginfo_class_FFI_CType_getAlignment arginfo_class_FFI_CType_getKind + +#define arginfo_class_FFI_CType_getAttributes arginfo_class_FFI_CType_getKind + +#define arginfo_class_FFI_CType_getEnumKind arginfo_class_FFI_CType_getKind + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_CType_getArrayElementType, 0, 0, FFI\\CType, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_FFI_CType_getArrayLength arginfo_class_FFI_CType_getKind + +#define arginfo_class_FFI_CType_getPointerType arginfo_class_FFI_CType_getArrayElementType + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_CType_getStructFieldNames, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_CType_getStructFieldOffset, 0, 1, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, field_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_CType_getStructFieldType, 0, 1, FFI\\CType, 0) + ZEND_ARG_TYPE_INFO(0, field_name, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_FFI_CType_getFuncABI arginfo_class_FFI_CType_getKind + +#define arginfo_class_FFI_CType_getFuncReturnType arginfo_class_FFI_CType_getArrayElementType + +#define arginfo_class_FFI_CType_getFuncArgCount arginfo_class_FFI_CType_getKind + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_CType_getFuncArgType, 0, 1, FFI\\CType, 0) + ZEND_ARG_TYPE_INFO(0, arg_index, IS_LONG, 0) +ZEND_END_ARG_INFO() + ZEND_METHOD(FFI, cdef); ZEND_METHOD(FFI, load); @@ -101,6 +140,21 @@ ZEND_METHOD(FFI, memset); ZEND_METHOD(FFI, string); ZEND_METHOD(FFI, isNull); ZEND_METHOD(FFI_CType, getName); +ZEND_METHOD(FFI_CType, getKind); +ZEND_METHOD(FFI_CType, getSize); +ZEND_METHOD(FFI_CType, getAlignment); +ZEND_METHOD(FFI_CType, getAttributes); +ZEND_METHOD(FFI_CType, getEnumKind); +ZEND_METHOD(FFI_CType, getArrayElementType); +ZEND_METHOD(FFI_CType, getArrayLength); +ZEND_METHOD(FFI_CType, getPointerType); +ZEND_METHOD(FFI_CType, getStructFieldNames); +ZEND_METHOD(FFI_CType, getStructFieldOffset); +ZEND_METHOD(FFI_CType, getStructFieldType); +ZEND_METHOD(FFI_CType, getFuncABI); +ZEND_METHOD(FFI_CType, getFuncReturnType); +ZEND_METHOD(FFI_CType, getFuncArgCount); +ZEND_METHOD(FFI_CType, getFuncArgType); static const zend_function_entry class_FFI_methods[] = { @@ -132,6 +186,21 @@ static const zend_function_entry class_FFI_CData_methods[] = { static const zend_function_entry class_FFI_CType_methods[] = { ZEND_ME(FFI_CType, getName, arginfo_class_FFI_CType_getName, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getKind, arginfo_class_FFI_CType_getKind, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getSize, arginfo_class_FFI_CType_getSize, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getAlignment, arginfo_class_FFI_CType_getAlignment, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getAttributes, arginfo_class_FFI_CType_getAttributes, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getEnumKind, arginfo_class_FFI_CType_getEnumKind, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getArrayElementType, arginfo_class_FFI_CType_getArrayElementType, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getArrayLength, arginfo_class_FFI_CType_getArrayLength, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getPointerType, arginfo_class_FFI_CType_getPointerType, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getStructFieldNames, arginfo_class_FFI_CType_getStructFieldNames, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getStructFieldOffset, arginfo_class_FFI_CType_getStructFieldOffset, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getStructFieldType, arginfo_class_FFI_CType_getStructFieldType, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getFuncABI, arginfo_class_FFI_CType_getFuncABI, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getFuncReturnType, arginfo_class_FFI_CType_getFuncReturnType, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getFuncArgCount, arginfo_class_FFI_CType_getFuncArgCount, ZEND_ACC_PUBLIC) + ZEND_ME(FFI_CType, getFuncArgType, arginfo_class_FFI_CType_getFuncArgType, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/ffi/tests/046.phpt b/ext/ffi/tests/046.phpt new file mode 100644 index 0000000000000..345cc84727bd2 --- /dev/null +++ b/ext/ffi/tests/046.phpt @@ -0,0 +1,95 @@ +--TEST-- +FFI 046: FFI::CType reflection API +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +getKind() === $x::TYPE_UINT8); +var_dump($x->getSize()); +var_dump($x->getAlignment()); + +$x = FFI::type("enum __attribute__((packed)) {a2, b2}"); +var_dump($x->getKind() === $x::TYPE_ENUM); +var_dump($x->getEnumKind() === $x::TYPE_UINT8); + +$x = FFI::type("char[5]"); +var_dump($x->getKind() === $x::TYPE_ARRAY); +var_dump($x->getSize()); +var_dump($x->getArrayElementType()->getKind() === $x::TYPE_CHAR); +var_dump($x->getArrayLength()); + +$x = FFI::type("void*"); +var_dump($x->getKind() === $x::TYPE_POINTER); +var_dump($x->getPointerType()->getKind() === $x::TYPE_VOID); + +$x = FFI::type("struct {double x; double y;}"); +var_dump($x->getKind() === $x::TYPE_STRUCT); +var_dump(($x->getAttributes() & $x::ATTR_UNION) != 0); +var_dump($x->getStructFieldNames()); +var_dump($x->getStructFieldOffset("x")); +var_dump($x->getStructFieldOffset("y")); +var_dump($x->getStructFieldType("x")->getKind() == $x::TYPE_DOUBLE); +var_dump($x->getStructFieldType("y")->getKind() == $x::TYPE_DOUBLE); + +$x = FFI::type("union {double x; double y;}"); +var_dump($x->getKind() === $x::TYPE_STRUCT); +var_dump(($x->getAttributes() & $x::ATTR_UNION) != 0); +var_dump($x->getStructFieldNames()); +var_dump($x->getStructFieldOffset("x")); +var_dump($x->getStructFieldOffset("y")); +var_dump($x->getStructFieldType("x")->getKind() == $x::TYPE_DOUBLE); +var_dump($x->getStructFieldType("y")->getKind() == $x::TYPE_DOUBLE); + +$x = FFI::type("void (*)(double,int32_t)"); +var_dump($x->getKind() === $x::TYPE_POINTER); +var_dump($x->getPointerType()->getKind() === $x::TYPE_FUNC); +var_dump($x->getPointerType()->getFuncReturnType()->getKind() === $x::TYPE_VOID); +var_dump($x->getPointerType()->getFuncArgCount()); +var_dump($x->getPointerType()->getFuncArgType(0)->getKind() === $x::TYPE_DOUBLE); +var_dump($x->getPointerType()->getFuncArgType(1)->getKind() === $x::TYPE_SINT32); +?> +--EXPECT-- +bool(true) +int(1) +int(1) +bool(true) +bool(true) +bool(true) +int(5) +bool(true) +int(5) +bool(true) +bool(true) +bool(true) +bool(false) +array(2) { + [0]=> + string(1) "x" + [1]=> + string(1) "y" +} +int(0) +int(8) +bool(true) +bool(true) +bool(true) +bool(true) +array(2) { + [0]=> + string(1) "x" + [1]=> + string(1) "y" +} +int(0) +int(0) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +int(2) +bool(true) +bool(true)