• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/tests/custom/17_lib_ffi/31_closure

  1 ffi.closure() creates a C function pointer bound to a ucode function. The
  2 result is an "ffi.closure" resource that can be passed to C functions
  3 expecting function pointers. It supports ptr(), tostring(), and cast() methods.
  4 
  5 Create a closure and pass it to qsort.
  6 
  7 -- Testcase --
  8 {%
  9 import * as ffi from 'ffi';
 10 
 11 ffi.cdef(`
 12     void qsort(void *base, size_t nmemb, size_t size,
 13                int (*compar)(const void *, const void *));
 14 `);
 15 
 16 let narr = ffi.ctype('int[5]', [56, 4, 12, 1, 5]);
 17 let qsort_fn = ffi.C.wrap('qsort');
 18 
 19 let cmp = ffi.closure('int (*)(const void *, const void *)',
 20                     (a, b) => a.deref('int') - b.deref('int'));
 21 qsort_fn(narr.ptr(), narr.length(), narr.itemsize(), cmp);
 22 
 23 print("sorted: ");
 24 for (let i = 0; i < 5; i++) {
 25     print(narr.get(i), " ");
 26 }
 27 print("\n");
 28 -- End --
 29 
 30 -- Expect stdout --
 31 sorted: 1 4 5 12 56 
 32 -- End --
 33 
 34 Closure ptr() returns a non-null pointer cdata.
 35 
 36 -- Testcase --
 37 {%
 38 import * as ffi from 'ffi';
 39 
 40 let cmp = ffi.closure('int (*)(const void *, const void *)',
 41                     (a, b) => a.deref('int') - b.deref('int'));
 42 
 43 let p = cmp.ptr();
 44 print(p != null, "\n");
 45 -- End --
 46 
 47 -- Expect stdout --
 48 true
 49 -- End --
 50 
 51 Closure tostring() shows the type and address.
 52 
 53 -- Testcase --
 54 {%
 55 import * as ffi from 'ffi';
 56 
 57 let cmp = ffi.closure('int (*)(const void *, const void *)',
 58                     (a, b) => a.deref('int') - b.deref('int'));
 59 
 60 let s = cmp.tostring();
 61 print(match(s, /^int \(\*\)\(\) 0x/) != null, "\n");
 62 -- End --
 63 
 64 -- Expect stdout --
 65 true
 66 -- End --
 67 
 68 Closure cast() to the same type returns a cdata.
 69 
 70 -- Testcase --
 71 {%
 72 import * as ffi from 'ffi';
 73 
 74 let cmp = ffi.closure('int (*)(const void *, const void *)',
 75                     (a, b) => a.deref('int') - b.deref('int'));
 76 
 77 let casted = cmp.cast('int (*)(const void *, const void *)');
 78 print(casted != null, "\n");
 79 print(match(casted.tostring(), /^int \(\*\)\(\) /) != null, "\n");
 80 -- End --
 81 
 82 -- Expect stdout --
 83 true
 84 true
 85 -- End --
 86 
 87 Pass closure as value for a struct function pointer member.
 88 
 89 -- Testcase --
 90 {%
 91 import * as ffi from 'ffi';
 92 
 93 ffi.cdef(`
 94     struct sorter { int (*compare)(const void *, const void *); };
 95 `);
 96 
 97 let cmp = ffi.closure('int (*)(const void *, const void *)',
 98                     (a, b) => a.deref('int') - b.deref('int'));
 99 
100 let s = ffi.ctype('struct sorter');
101 s.set('compare', cmp);
102 print("set ok", "\n");
103 -- End --
104 
105 -- Expect stdout --
106 set ok
107 -- End --
108 
109 ffi.cast() accepts a closure as the source value.
110 
111 -- Testcase --
112 {%
113 import * as ffi from 'ffi';
114 
115 let cmp = ffi.closure('int (*)(const void *, const void *)',
116                     (a, b) => a.deref('int') - b.deref('int'));
117 
118 let casted = ffi.cast('int (*)(const void *, const void *)', cmp);
119 print(casted != null, "\n");
120 -- End --
121 
122 -- Expect stdout --
123 true
124 -- End --
125 
126 Closing over local variables in a callback.
127 
128 -- Testcase --
129 {%
130 import * as ffi from 'ffi';
131 
132 ffi.cdef(`
133     void qsort(void *base, size_t nmemb, size_t size,
134                int (*compar)(const void *, const void *));
135 `);
136 
137 let factor = 10;
138 let narr = ffi.ctype('int[4]', [30, 10, 20, 40]);
139 let qsort_fn = ffi.C.wrap('qsort');
140 
141 let cmp = ffi.closure('int (*)(const void *, const void *)',
142                     (a, b) => (a.deref('int') / factor) - (b.deref('int') / factor));
143 qsort_fn(narr.ptr(), narr.length(), narr.itemsize(), cmp);
144 
145 print("sorted: ");
146 for (let i = 0; i < 4; i++) {
147     print(narr.get(i), " ");
148 }
149 print("\n");
150 -- End --
151 
152 -- Expect stdout --
153 sorted: 10 20 30 40 
154 -- End --
155 
156 Multiple closures can coexist independently.
157 
158 -- Testcase --
159 {%
160 import * as ffi from 'ffi';
161 
162 ffi.cdef(`
163     void qsort(void *base, size_t nmemb, size_t size,
164                int (*compar)(const void *, const void *));
165 `);
166 
167 let qsort_fn = ffi.C.wrap('qsort');
168 let arr = ffi.ctype('int[4]', [4, 3, 2, 1]);
169 
170 let asc = ffi.closure('int (*)(const void *, const void *)',
171                     (a, b) => a.deref('int') - b.deref('int'));
172 let desc = ffi.closure('int (*)(const void *, const void *)',
173                      (a, b) => b.deref('int') - a.deref('int'));
174 
175 qsort_fn(arr.ptr(), arr.length(), arr.itemsize(), asc);
176 print("asc: ");
177 for (let i = 0; i < 4; i++) {
178     print(arr.get(i), " ");
179 }
180 print("\n");
181 
182 qsort_fn(arr.ptr(), arr.length(), arr.itemsize(), desc);
183 print("desc: ");
184 for (let i = 0; i < 4; i++) {
185     print(arr.get(i), " ");
186 }
187 print("\n");
188 -- End --
189 
190 -- Expect stdout --
191 asc: 1 2 3 4 
192 desc: 4 3 2 1 
193 -- End --

This page was automatically generated by LXR 0.3.1.  •  OpenWrt