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