|  | 
|  | 1 | +--TEST-- | 
|  | 2 | +GH-16013 (endianness issue with FFI) | 
|  | 3 | +--EXTENSIONS-- | 
|  | 4 | +ffi | 
|  | 5 | +zend_test | 
|  | 6 | +--FILE-- | 
|  | 7 | +<?php | 
|  | 8 | +require_once('utils.inc'); | 
|  | 9 | + | 
|  | 10 | +$header = <<<HEADER | 
|  | 11 | +enum bug_gh16013_enum { | 
|  | 12 | +	BUG_GH16013_A = 1, | 
|  | 13 | +	BUG_GH16013_B = 2, | 
|  | 14 | +}; | 
|  | 15 | +struct bug_gh16013_int_struct { | 
|  | 16 | +	int field; | 
|  | 17 | +}; | 
|  | 18 | +struct bug_gh16013_callback_struct { | 
|  | 19 | +	int8_t (*return_int8)(int8_t); | 
|  | 20 | +	uint8_t (*return_uint8)(uint8_t); | 
|  | 21 | +	int16_t (*return_int16)(int16_t); | 
|  | 22 | +	uint16_t (*return_uint16)(uint16_t); | 
|  | 23 | +	int32_t (*return_int32)(int32_t); | 
|  | 24 | +	uint32_t (*return_uint32)(uint32_t); | 
|  | 25 | +	float (*return_float)(float); | 
|  | 26 | +	struct bug_gh16013_int_struct (*return_struct)(struct bug_gh16013_int_struct); | 
|  | 27 | +	enum bug_gh16013_enum (*return_enum)(enum bug_gh16013_enum); | 
|  | 28 | +}; | 
|  | 29 | +
 | 
|  | 30 | +char bug_gh16013_return_char(); | 
|  | 31 | +bool bug_gh16013_return_bool(); | 
|  | 32 | +short bug_gh16013_return_short(); | 
|  | 33 | +int bug_gh16013_return_int(); | 
|  | 34 | +enum bug_gh16013_enum bug_gh16013_return_enum(); | 
|  | 35 | +struct bug_gh16013_int_struct bug_gh16013_return_struct(); | 
|  | 36 | +HEADER; | 
|  | 37 | + | 
|  | 38 | +if (PHP_OS_FAMILY !== 'Windows') { | 
|  | 39 | +    $ffi = FFI::cdef($header); | 
|  | 40 | +} else { | 
|  | 41 | +    try { | 
|  | 42 | +        $ffi = FFI::cdef($header, 'php_zend_test.dll'); | 
|  | 43 | +    } catch (FFI\Exception $ex) { | 
|  | 44 | +        $ffi = FFI::cdef($header, ffi_get_php_dll_name()); | 
|  | 45 | +    } | 
|  | 46 | +} | 
|  | 47 | + | 
|  | 48 | +echo "--- Return values ---\n"; | 
|  | 49 | +var_dump($ffi->bug_gh16013_return_char()); | 
|  | 50 | +var_dump($ffi->bug_gh16013_return_bool()); | 
|  | 51 | +var_dump($ffi->bug_gh16013_return_short()); | 
|  | 52 | +var_dump($ffi->bug_gh16013_return_int()); | 
|  | 53 | +var_dump($ffi->bug_gh16013_return_enum()); | 
|  | 54 | +var_dump($ffi->bug_gh16013_return_struct()); | 
|  | 55 | + | 
|  | 56 | +echo "--- Callback values ---\n"; | 
|  | 57 | +$bug_gh16013_callback_struct = $ffi->new('struct bug_gh16013_callback_struct'); | 
|  | 58 | +$bug_gh16013_callback_struct->return_int8 = function($val) use($ffi) { | 
|  | 59 | +    $cdata = $ffi->new('int8_t'); | 
|  | 60 | +    $cdata->cdata = $val; | 
|  | 61 | +    return $cdata; | 
|  | 62 | +}; | 
|  | 63 | +$bug_gh16013_callback_struct->return_uint8 = function($val) use($ffi) { | 
|  | 64 | +    $cdata = $ffi->new('uint8_t'); | 
|  | 65 | +    $cdata->cdata = $val; | 
|  | 66 | +    return $cdata; | 
|  | 67 | +}; | 
|  | 68 | +$bug_gh16013_callback_struct->return_int16 = function($val) use($ffi) { | 
|  | 69 | +    $cdata = $ffi->new('int16_t'); | 
|  | 70 | +    $cdata->cdata = $val; | 
|  | 71 | +    return $cdata; | 
|  | 72 | +}; | 
|  | 73 | +$bug_gh16013_callback_struct->return_uint16 = function($val) use($ffi) { | 
|  | 74 | +    $cdata = $ffi->new('uint16_t'); | 
|  | 75 | +    $cdata->cdata = $val; | 
|  | 76 | +    return $cdata; | 
|  | 77 | +}; | 
|  | 78 | +$bug_gh16013_callback_struct->return_int32 = function($val) use($ffi) { | 
|  | 79 | +    $cdata = $ffi->new('int32_t'); | 
|  | 80 | +    $cdata->cdata = $val; | 
|  | 81 | +    return $cdata; | 
|  | 82 | +}; | 
|  | 83 | +$bug_gh16013_callback_struct->return_uint32 = function($val) use($ffi) { | 
|  | 84 | +    $cdata = $ffi->new('uint32_t'); | 
|  | 85 | +    $cdata->cdata = $val; | 
|  | 86 | +    return $cdata; | 
|  | 87 | +}; | 
|  | 88 | +$bug_gh16013_callback_struct->return_float = function($val) use($ffi) { | 
|  | 89 | +    $cdata = $ffi->new('float'); | 
|  | 90 | +    $cdata->cdata = $val; | 
|  | 91 | +    return $cdata; | 
|  | 92 | +}; | 
|  | 93 | +$bug_gh16013_callback_struct->return_struct = function($val) use($ffi) { | 
|  | 94 | +    return $val; | 
|  | 95 | +}; | 
|  | 96 | +$bug_gh16013_callback_struct->return_enum = function($val) use($ffi) { | 
|  | 97 | +    $cdata = $ffi->new('enum bug_gh16013_enum'); | 
|  | 98 | +    $cdata->cdata = $val; | 
|  | 99 | +    return $cdata; | 
|  | 100 | +}; | 
|  | 101 | + | 
|  | 102 | +var_dump(($bug_gh16013_callback_struct->return_int8)(-4)); | 
|  | 103 | +var_dump(($bug_gh16013_callback_struct->return_uint8)(4)); | 
|  | 104 | +var_dump(($bug_gh16013_callback_struct->return_int16)(-10000)); | 
|  | 105 | +var_dump(($bug_gh16013_callback_struct->return_uint16)(10000)); | 
|  | 106 | +var_dump(($bug_gh16013_callback_struct->return_int32)(-100000)); | 
|  | 107 | +var_dump(($bug_gh16013_callback_struct->return_uint32)(100000)); | 
|  | 108 | +var_dump(($bug_gh16013_callback_struct->return_float)(12.34)); | 
|  | 109 | +$struct = $ffi->new('struct bug_gh16013_int_struct'); | 
|  | 110 | +$struct->field = 10; | 
|  | 111 | +var_dump(($bug_gh16013_callback_struct->return_struct)($struct)); | 
|  | 112 | +var_dump(($bug_gh16013_callback_struct->return_enum)($ffi->BUG_GH16013_B)); | 
|  | 113 | +?> | 
|  | 114 | +--EXPECT-- | 
|  | 115 | +--- Return values --- | 
|  | 116 | +string(1) "A" | 
|  | 117 | +bool(true) | 
|  | 118 | +int(12345) | 
|  | 119 | +int(123456789) | 
|  | 120 | +int(2) | 
|  | 121 | +object(FFI\CData:struct bug_gh16013_int_struct)#2 (1) { | 
|  | 122 | +  ["field"]=> | 
|  | 123 | +  int(123456789) | 
|  | 124 | +} | 
|  | 125 | +--- Callback values --- | 
|  | 126 | +int(-4) | 
|  | 127 | +int(4) | 
|  | 128 | +int(-10000) | 
|  | 129 | +int(10000) | 
|  | 130 | +int(-100000) | 
|  | 131 | +int(100000) | 
|  | 132 | +float(12.34000015258789) | 
|  | 133 | +object(FFI\CData:struct bug_gh16013_int_struct)#13 (1) { | 
|  | 134 | +  ["field"]=> | 
|  | 135 | +  int(10) | 
|  | 136 | +} | 
|  | 137 | +int(2) | 
0 commit comments