3737import java .lang .reflect .Method ;
3838import java .lang .reflect .Modifier ;
3939import java .util .ArrayList ;
40+ import java .util .Arrays ;
41+ import java .util .HashMap ;
42+ import java .util .LinkedHashMap ;
4043import java .util .List ;
44+ import java .util .Map ;
4145
4246import org .bridj .ann .Alignment ;
4347import org .bridj .ann .Array ;
4448import org .bridj .ann .Bits ;
4549import org .bridj .ann .Field ;
4650import org .bridj .ann .Union ;
4751
52+ import com .fasterxml .classmate .AnnotationConfiguration ;
53+ import com .fasterxml .classmate .AnnotationInclusion ;
54+ import com .fasterxml .classmate .Filter ;
55+ import com .fasterxml .classmate .MemberResolver ;
56+ import com .fasterxml .classmate .ResolvedType ;
57+ import com .fasterxml .classmate .ResolvedTypeWithMembers ;
58+ import com .fasterxml .classmate .TypeResolver ;
59+ import com .fasterxml .classmate .members .RawField ;
60+ import com .fasterxml .classmate .members .RawMethod ;
61+ import com .fasterxml .classmate .members .ResolvedField ;
62+ import com .fasterxml .classmate .members .ResolvedMember ;
63+ import com .fasterxml .classmate .members .ResolvedMethod ;
64+
4865class StructFieldDeclaration {
4966
5067 final StructFieldDescription desc = new StructFieldDescription ();
5168 Method setter ;
69+ ResolvedMember resolvedSetter ;
5270 long index = -1 , unionWith = -1 ;//, byteOffset = -1;
5371 Class <?> valueClass ;
5472 Class <?> declaringClass ;
@@ -58,6 +76,7 @@ public String toString() {
5876 return desc .name + " (index = " + index + (unionWith < 0 ? "" : ", unionWith = " + unionWith ) + ", desc = " + desc + ")" ;
5977 }
6078
79+ @ Deprecated
6180 protected static boolean acceptFieldGetter (Member member , boolean getter ) {
6281 if ((member instanceof Method ) && ((Method ) member ).getParameterTypes ().length != (getter ? 0 : 1 )) {
6382 return false ;
@@ -71,16 +90,30 @@ protected static boolean acceptFieldGetter(Member member, boolean getter) {
7190
7291 return !Modifier .isStatic (modifiers );
7392 }
93+
94+ protected static boolean acceptFieldGetter (ResolvedMember <?> member , boolean getter ) {
95+ if ((member instanceof ResolvedMethod ) && ((ResolvedMethod ) member ).getRawMember ().getParameterTypes ().length != (getter ? 0 : 1 )) {
96+ return false ;
97+ }
98+
99+ if (member .get (Field .class ) == null ) {
100+ return false ;
101+ }
102+
103+ return !member .isStatic ();
104+ }
74105
75106 /**
76107 * Creates a list of structure fields
77108 */
109+ @ Deprecated
78110 protected static List <StructFieldDeclaration > listFields (Class <?> structClass ) {
79111 List <StructFieldDeclaration > list = new ArrayList <StructFieldDeclaration >();
80112 for (Method method : structClass .getMethods ()) {
81113 if (acceptFieldGetter (method , true )) {
82114 StructFieldDeclaration io = fromGetter (method );
83115 try {
116+ // this only works when the names are equal, does not support setXXX methods.
84117 Method setter = structClass .getMethod (method .getName (), io .valueClass );
85118 if (acceptFieldGetter (setter , false )) {
86119 io .setter = setter ;
@@ -110,7 +143,123 @@ protected static List<StructFieldDeclaration> listFields(Class<?> structClass) {
110143
111144 return list ;
112145 }
146+
147+ protected static List <StructFieldDeclaration > listFields2 (Class <?> structClass ) {
148+ List <StructFieldDeclaration > list = new ArrayList <StructFieldDeclaration >();
149+ ResolvedTypeWithMembers resolvedStruct = resolveType (structClass );
150+ for (ResolvedMethod method : resolvedStruct .getMemberMethods ()) {
151+ if (acceptFieldGetter (method , true )) {
152+ StructFieldDeclaration io = fromGetter (method );
153+ try {
154+ // this only works when the names are equal, does not support setXXX methods.
155+ ResolvedMethod setter = getMethod ( resolvedStruct .getMemberMethods (), method .getName (), io .valueClass );
156+ if (acceptFieldGetter (setter , false )) {
157+ io .setter = setter .getRawMember ();
158+ }
159+ } catch (Exception ex ) {
160+ //assert BridJ.info("No setter for getter " + method);
161+ }
162+ if (io != null ) {
163+ list .add (io );
164+ }
165+ }
166+ }
113167
168+ int nFieldFields = 0 ;
169+ for ( ResolvedField field : resolvedStruct .getMemberFields ()) {
170+ if (acceptFieldGetter (field , true )) {
171+ StructFieldDeclaration io = StructFieldDeclaration .fromField (field );
172+ if (io != null ) {
173+ list .add (io );
174+ nFieldFields ++;
175+ }
176+ }
177+ }
178+ if (nFieldFields > 0 && BridJ .warnStructFields ) {
179+ BridJ .warning ("Struct " + structClass .getName () + " has " + nFieldFields + " struct fields implemented as Java fields, which won't give the best performance and might require counter-intuitive calls to BridJ.readFromNative / .writeToNative. Please consider using JNAerator to generate your struct instead, or use BRIDJ_WARN_STRUCT_FIELDS=0 or -Dbridj.warnStructFields=false to mute this warning." );
180+ }
181+
182+ return list ;
183+ }
184+
185+ public static ResolvedMethod getMethod ( ResolvedMethod [] methods , String name , Class <?>... params ) {
186+ METHODS : for ( ResolvedMethod method : methods ) {
187+ if ( !name .equals (method .getName ()) ) continue METHODS ;
188+ if ( params .length != method .getArgumentCount ()) continue METHODS ;
189+ for ( int i = 0 ; i < params .length ; i ++ ) {
190+ if ( !method .getArgumentType (i ).isInstanceOf (params [i ])) continue METHODS ;
191+ }
192+ return method ;
193+ }
194+ return null ;
195+ }
196+
197+ protected static String nameForMember ( ResolvedMember <?> member ) {
198+ String name = member .getName ();
199+ if (name .matches ("get[A-Z].*" )) {
200+ return Character .toLowerCase (name .charAt (3 )) + name .substring (4 );
201+ } else if ( name .matches ("set[A-Z].*" )) {
202+ return Character .toLowerCase (name .charAt (3 )) + name .substring (4 );
203+ } else {
204+ return name ;
205+ }
206+ }
207+
208+ protected static ResolvedTypeWithMembers resolveType ( Class <?> structClass ) {
209+ TypeResolver resolver = new TypeResolver ();
210+ ResolvedType classType = resolver .resolve (structClass );
211+ MemberResolver mr = new MemberResolver (resolver );
212+ mr .setMethodFilter (new Filter <RawMethod >() {
213+ @ Override
214+ public boolean include ( RawMethod method ) {
215+ return
216+ method .getRawMember ().getParameterTypes ().length < 2 &&
217+ !method .isStatic ();
218+ }
219+ });
220+ mr .setFieldFilter (new Filter <RawField >() {
221+ @ Override
222+ public boolean include ( RawField field ) {
223+ return !field .isStatic ();
224+ }
225+ });
226+ AnnotationConfiguration annConfig = new AnnotationConfiguration .StdConfiguration (AnnotationInclusion .INCLUDE_BUT_DONT_INHERIT );
227+ return mr .resolve (classType , annConfig , null );
228+ }
229+
230+ protected static <T extends Member > void updateDecl (StructFieldDeclaration decl , ResolvedMember <T > member ) {
231+ decl .declaringClass = member .getRawMember ().getDeclaringClass ();
232+ Field field = member .get (Field .class );
233+ Bits bits = member .get (Bits .class );
234+ Alignment alignment = member .get (Alignment .class );
235+ Array arr = member .get (Array .class );
236+
237+ if ( field != null ) {
238+ decl .index = field .value ();
239+ decl .unionWith = field .unionWith ();
240+ }
241+ if ( decl .unionWith < 0 && decl .declaringClass .getAnnotation (Union .class ) != null ) {
242+ decl .unionWith = 0 ;
243+ }
244+ if ( bits != null ) {
245+ decl .desc .bitLength = bits .value ();
246+ }
247+ if ( alignment != null ) {
248+ decl .desc .alignment = alignment .value ();
249+ }
250+ if ( arr != null ) {
251+ long length = 1 ;
252+ for (long dim : arr .value ()) {
253+ length *= dim ;
254+ }
255+ decl .desc .arrayLength = length ;
256+ decl .desc .isArray = true ;
257+ }
258+ decl .desc .isCLong = member .get (org .bridj .ann .CLong .class ) != null ;
259+ decl .desc .isSizeT = member .get (org .bridj .ann .Ptr .class ) != null ;
260+ }
261+
262+ @ Deprecated
114263 protected static StructFieldDeclaration fromField (java .lang .reflect .Field getter ) {
115264 StructFieldDeclaration field = fromMember ((Member ) getter );
116265 field .desc .field = getter ;
@@ -119,6 +268,15 @@ protected static StructFieldDeclaration fromField(java.lang.reflect.Field getter
119268 return field ;
120269 }
121270
271+ protected static StructFieldDeclaration fromField (ResolvedField getter ) {
272+ StructFieldDeclaration field = fromMember ((ResolvedField ) getter );
273+ field .desc .field = getter .getRawMember ();
274+ field .desc .valueType = getter .getType ();
275+ field .valueClass = getter .getType ().getErasedType ();
276+ return field ;
277+ }
278+
279+ @ Deprecated
122280 protected static StructFieldDeclaration fromGetter (Method getter ) {
123281 StructFieldDeclaration field = fromMember ((Member ) getter );
124282 field .desc .getter = getter ;
@@ -127,6 +285,15 @@ protected static StructFieldDeclaration fromGetter(Method getter) {
127285 return field ;
128286 }
129287
288+ protected static StructFieldDeclaration fromGetter (ResolvedMethod getter ) {
289+ StructFieldDeclaration field = fromMember ((ResolvedMember ) getter );
290+ field .desc .getter = getter .getRawMember ();
291+ field .desc .valueType = getter .getReturnType ();
292+ field .valueClass = getter .getReturnType ().getErasedType ();
293+ return field ;
294+ }
295+
296+ @ Deprecated
130297 private static StructFieldDeclaration fromMember (Member member ) {
131298 StructFieldDeclaration field = new StructFieldDeclaration ();
132299 field .declaringClass = member .getDeclaringClass ();
@@ -170,4 +337,47 @@ private static StructFieldDeclaration fromMember(Member member) {
170337 field .desc .isSizeT = isAnnotationPresent (org .bridj .ann .Ptr .class , getter );
171338 return field ;
172339 }
340+
341+ private static StructFieldDeclaration fromMember (ResolvedMember <?> member ) {
342+ StructFieldDeclaration field = new StructFieldDeclaration ();
343+ field .declaringClass = member .getRawMember ().getDeclaringClass ();
344+
345+ String name = member .getName ();
346+ if (name .matches ("get[A-Z].*" )) {
347+ name = Character .toLowerCase (name .charAt (3 )) + name .substring (4 );
348+ }
349+
350+ field .desc .name = name ;
351+
352+ Field fil = member .get (Field .class );
353+ Bits bits = member .get (Bits .class );
354+ Alignment alignment = member .get (Alignment .class );
355+ Array arr = member .get (Array .class );
356+ if (fil != null ) {
357+ field .index = fil .value ();
358+ //field.byteOffset = fil.offset();
359+ field .unionWith = fil .unionWith ();
360+ }
361+ if (field .unionWith < 0 && field .declaringClass .getAnnotation (Union .class ) != null ) {
362+ field .unionWith = 0 ;
363+ }
364+
365+ if (bits != null ) {
366+ field .desc .bitLength = bits .value ();
367+ }
368+ if (alignment != null ) {
369+ field .desc .alignment = alignment .value ();
370+ }
371+ if (arr != null ) {
372+ long length = 1 ;
373+ for (long dim : arr .value ()) {
374+ length *= dim ;
375+ }
376+ field .desc .arrayLength = length ;
377+ field .desc .isArray = true ;
378+ }
379+ field .desc .isCLong = member .get (org .bridj .ann .CLong .class ) != null ;
380+ field .desc .isSizeT = member .get (org .bridj .ann .Ptr .class ) != null ;
381+ return field ;
382+ }
173383}
0 commit comments