1 A structure taken by value is described to libffi by a type descriptor which has 2 to match the memory layout the ABI uses: a NULL terminated vector of its 3 members, and a plain byte alignment rather than the base 2 logarithm the CType 4 stores. Without the vector, initialize_aggregate() cannot derive size and 5 alignment and ffi_prep_cif() dies while dereferencing the absent members. 6 7 A system library offers no entry point taking a caller defined structure, so 8 each testcase ships the source of one, compiles it with cc, and abstains when 9 no C compiler is available. 10 11 Compare two structures taken by value. 12 13 -- Testcase -- 14 {% 15 import * as ffi from 'ffi'; 16 17 let src = TESTFILES_PATH + '/uctestlib.c'; 18 let so = TESTFILES_PATH + '/uctestlib.so'; 19 20 if (system([ 'cc', '-shared', '-fPIC', '-o', so, src ]) != 0) 21 exit(77); 22 23 let lib = ffi.dlopen(so, false, ` 24 struct point { int x; int y; }; 25 int uctest_cmp_val(struct point a, struct point b); 26 `); 27 28 // Two structures in one signature are only placed at the offsets the ABI 29 // uses when the descriptor carries an alignment of eight bytes rather than 30 // the logarithm of it. 31 print("equal: ", lib.uctest_cmp_val({ x: 1, y: 2 }, { x: 1, y: 2 }), "\n"); 32 print("less: ", lib.uctest_cmp_val({ x: 1, y: 2 }, { x: 3, y: 4 }), "\n"); 33 print("more: ", lib.uctest_cmp_val({ x: 3, y: 4 }, { x: 1, y: 2 }), "\n"); 34 %} 35 -- End -- 36 37 -- File uctestlib.c -- 38 struct point { 39 int x; 40 int y; 41 }; 42 43 int 44 uctest_cmp_val(struct point a, struct point b) 45 { 46 if (a.x != b.x) 47 return a.x < b.x ? -1 : 1; 48 49 return a.y == b.y ? 0 : (a.y < b.y ? -1 : 1); 50 } 51 -- End -- 52 53 -- Expect stdout -- 54 equal: 0 55 less: -1 56 more: 1 57 -- End -- 58 59 60 Add up the members of a nested structure taken by value. 61 62 -- Testcase -- 63 {% 64 import * as ffi from 'ffi'; 65 66 let src = TESTFILES_PATH + '/uctestlib.c'; 67 let so = TESTFILES_PATH + '/uctestlib.so'; 68 69 if (system([ 'cc', '-shared', '-fPIC', '-o', so, src ]) != 0) 70 exit(77); 71 72 let lib = ffi.dlopen(so, false, ` 73 struct point { int x; int y; }; 74 struct nested { struct point p; long sum; }; 75 long uctest_nested_val(struct nested n); 76 `); 77 78 // A nested structure is a member like any other, so the vector has to be 79 // built all the way down. 80 print("nested: ", lib.uctest_nested_val({ p: { x: 1, y: 2 }, sum: 30 }), "\n"); 81 %} 82 -- End -- 83 84 -- File uctestlib.c -- 85 struct point { 86 int x; 87 int y; 88 }; 89 90 struct nested { 91 struct point p; 92 long sum; 93 }; 94 95 long 96 uctest_nested_val(struct nested n) 97 { 98 return n.p.x + n.p.y + n.sum; 99 } 100 -- End -- 101 102 -- Expect stdout -- 103 nested: 33 104 -- End -- 105 106 107 Read the members of a wide structure taken by value. 108 109 -- Testcase -- 110 {% 111 import * as ffi from 'ffi'; 112 113 let src = TESTFILES_PATH + '/uctestlib.c'; 114 let so = TESTFILES_PATH + '/uctestlib.so'; 115 116 if (system([ 'cc', '-shared', '-fPIC', '-o', so, src ]) != 0) 117 exit(77); 118 119 let lib = ffi.dlopen(so, false, ` 120 struct wide { long a; long b; long c; }; 121 long uctest_wide_val(struct wide w); 122 `); 123 124 // A structure too large for the general purpose registers is passed on the 125 // stack, where the ABI only finds it if the descriptor's size and 126 // alignment describe its memory layout. 127 print("wide: ", lib.uctest_wide_val({ a: 1, b: 2, c: 3 }), "\n"); 128 %} 129 -- End -- 130 131 -- File uctestlib.c -- 132 struct wide { 133 long a; 134 long b; 135 long c; 136 }; 137 138 long 139 uctest_wide_val(struct wide w) 140 { 141 return w.a * 10000 + w.b * 100 + w.c; 142 } 143 -- End -- 144 145 -- Expect stdout -- 146 wide: 10203 147 -- End --
This page was automatically generated by LXR 0.3.1. • OpenWrt