xref: /PHP-8.3/ext/ffi/tests/gh11934.phpt (revision 0b9702c9)
1--TEST--
2Feature GH-11934 (Allow to pass CData into struct and/or union fields)
3--EXTENSIONS--
4ffi
5--INI--
6ffi.enable=1
7--FILE--
8<?php
9
10$cdef = FFI::cdef();
11
12echo "--- Primitive types ---\n";
13
14// Choose integer numbers off the maximum to test copy
15$types = [
16    'uint8_t' => 200,
17    'uint16_t' => 16000,
18    'uint32_t' => 1000_000,
19    'uint64_t' => PHP_INT_MAX - 100,
20    'int8_t' => -100,
21    'int16_t' => -16000,
22    'int32_t' => -1000_000,
23    'int64_t' => PHP_INT_MIN + 100,
24    'char' => 'F',
25    'bool' => false,
26    'float' => 1.00,
27    'double' => -1.00,
28];
29
30// Positive test
31foreach ($types as $type => $value) {
32    $source = $cdef->new($type);
33    $source->cdata = $value;
34    $struct = $cdef->new("struct { $type field; }");
35    $struct->field = $source;
36    echo "Positive test $type: ";
37    var_dump($struct->field === $value);
38}
39
40// Negative test
41$dummy = $cdef->new("int[2]");
42foreach ($types as $type => $value) {
43    $struct = $cdef->new("struct { int field; }");
44    $struct->field = $dummy;
45}
46
47// Enum test
48$enum_definition = "enum { A, B, C, D }";
49$source = $cdef->new($enum_definition);
50$source->cdata = 2;
51$struct = $cdef->new("struct { $enum_definition field; }");
52$struct->field = $source;
53echo "Positive test enum: ";
54var_dump($struct->field === $source->cdata);
55$struct->field = $dummy;
56
57echo "--- Struct ---\n";
58
59// Nested structs
60$cdef = FFI::cdef("
61    struct inner_struct {
62        int data[1];
63    };
64    struct my_struct {
65        int foo;
66        int bar;
67        struct inner_struct inner;
68    };
69    struct my_nesting_struct {
70        struct my_struct field;
71    };");
72$source = $cdef->new("struct my_struct");
73$source->foo = 123;
74$source->bar = 456;
75$source->inner->data[0] = 789;
76$struct = $cdef->new("struct my_nesting_struct");
77$struct->field = $source;
78var_dump($struct->field->foo === 123 && $struct->field->bar === 456 && $struct->field->inner->data[0] === 789);
79
80echo "--- Callback return type ---\n";
81
82$ffi = FFI::cdef('
83typedef uint32_t (*test_callback)();
84typedef struct {
85	test_callback call_me;
86} my_struct;
87');
88
89$struct = $ffi->new('my_struct');
90$struct->call_me = function () use ($ffi) {
91	$int = $ffi->new('uint32_t');
92	$int->cdata = 42;
93	return $int;
94};
95
96var_dump(($struct->call_me)());
97
98echo "--- Other FFI\CData assignment ---\n";
99
100$ffi = FFI::cdef('');
101
102$source = $ffi->new('uint32_t');
103$source->cdata = 123;
104$target = $ffi->new('uint32_t');
105$target->cdata = $source;
106
107var_dump($target->cdata);
108
109echo "--- Array element ---\n";
110
111$ffi = FFI::cdef('');
112
113$source = $ffi->new('uint32_t');
114$source->cdata = 123;
115$target = $ffi->new('uint32_t[1]');
116$target[0] = $source;
117
118var_dump($target[0]);
119
120?>
121--EXPECTF--
122--- Primitive types ---
123Positive test uint8_t: bool(true)
124Positive test uint16_t: bool(true)
125Positive test uint32_t: bool(true)
126Positive test uint64_t: bool(true)
127Positive test int8_t: bool(true)
128Positive test int16_t: bool(true)
129Positive test int32_t: bool(true)
130Positive test int64_t: bool(true)
131Positive test char: bool(true)
132Positive test bool: bool(true)
133Positive test float: bool(true)
134Positive test double: bool(true)
135
136Warning: Object of class FFI\CData could not be converted to int in %s on line %d
137
138Warning: Object of class FFI\CData could not be converted to int in %s on line %d
139
140Warning: Object of class FFI\CData could not be converted to int in %s on line %d
141
142Warning: Object of class FFI\CData could not be converted to int in %s on line %d
143
144Warning: Object of class FFI\CData could not be converted to int in %s on line %d
145
146Warning: Object of class FFI\CData could not be converted to int in %s on line %d
147
148Warning: Object of class FFI\CData could not be converted to int in %s on line %d
149
150Warning: Object of class FFI\CData could not be converted to int in %s on line %d
151
152Warning: Object of class FFI\CData could not be converted to int in %s on line %d
153
154Warning: Object of class FFI\CData could not be converted to int in %s on line %d
155
156Warning: Object of class FFI\CData could not be converted to int in %s on line %d
157
158Warning: Object of class FFI\CData could not be converted to int in %s on line %d
159Positive test enum: bool(true)
160
161Warning: Object of class FFI\CData could not be converted to int in %s on line %d
162--- Struct ---
163bool(true)
164--- Callback return type ---
165int(42)
166--- Other FFI\CData assignment ---
167int(123)
168--- Array element ---
169int(123)
170