001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj; 032import java.lang.reflect.TypeVariable; 033import java.lang.reflect.WildcardType; 034import org.bridj.CallIO.NativeObjectHandler; 035import org.bridj.util.*; 036import java.lang.reflect.ParameterizedType; 037import java.lang.reflect.Method; 038import java.lang.reflect.Modifier; 039import java.lang.reflect.Member; 040import java.lang.reflect.AnnotatedElement; 041import java.lang.reflect.Type; 042import java.nio.*; 043import java.util.ArrayList; 044import java.util.Collections; 045import java.util.Comparator; 046import java.util.HashMap; 047import java.util.LinkedHashMap; 048import java.util.HashSet; 049import java.util.List; 050import java.util.Map; 051import java.util.TreeMap; 052import java.util.Set; 053import java.util.concurrent.*; 054import org.bridj.ann.Virtual; 055import org.bridj.ann.Array; 056import org.bridj.ann.Union; 057import org.bridj.ann.Bits; 058import org.bridj.ann.Field; 059import org.bridj.ann.Struct; 060import org.bridj.ann.Alignment; 061import static org.bridj.Pointer.*; 062import static org.bridj.StructUtils.*; 063 064/** 065 * Object responsible for reading and writing of a C struct's fields.<br> 066 * End-users should not use this class, it's used by runtimes.<br> 067 * See {@link org.bridj.StructDescription}. 068 * @author ochafik 069 */ 070public class StructIO { 071 072 static Map<Type, StructIO> structIOs = new HashMap<Type, StructIO>(); 073 074 public static StructIO getInstance(Type structType) { 075 return getInstance(Utils.getClass(structType), structType); 076 } 077 public static StructIO getInstance(Class structClass, Type structType) { 078 synchronized (structIOs) { 079 StructIO io = structIOs.get(structType == null ? structClass : structType); 080 if (io == null) { 081 io = new StructIO(structClass, structType); 082 if (io != null) 083 registerStructIO(structClass, structType, io); 084 } 085 return (StructIO)io; 086 } 087 } 088 089 public static synchronized StructIO registerStructIO(Class structClass, Type structType, StructIO io) { 090 structIOs.put(structType, io); 091 return io; 092 } 093 094 protected PointerIO<?> pointerIO; 095 public final StructDescription desc; 096 097 public StructIO(Class<?> structClass, Type structType) { 098 this.desc = new StructDescription(structClass, structType, StructCustomizer.getInstance(structClass)); 099 // Don't call build here, for recursive initialization cases (TODO test this) 100 } 101 102 @Override 103 public String toString() { 104 return "StructIO(" + desc + ")"; 105 } 106 107 public boolean equal(StructObject a, StructObject b) { 108 return compare(a, b) == 0; 109 } 110 public int compare(StructObject a, StructObject b) { 111 return StructUtils.compare(a, b, desc.getSolidRanges()); 112 } 113 114 public final String describe(StructObject struct) { 115 return desc.describe(struct); 116 } 117 118 /** 119 * Write struct fields implemented as Java fields to the corresponding native memory (Java fields are written to native memory).<br> 120 * This does not concern normal structs as generated by JNAerator (which use getters and setters methods that read and write the fields directly from / to the native memory), but rather structs that are in the JNA style. 121 */ 122 public final void writeFieldsToNative(StructObject struct) { 123 desc.build(); 124 if (!desc.hasFieldFields) 125 return; 126 try { 127 for (StructFieldDescription fd : desc.fields) { 128 if (fd.field == null) 129 continue; 130 131 if (fd.isArray) 132 continue; 133 134 Object value = fd.field.get(struct); 135 if (value instanceof NativeObject) {//fd.isNativeObject) { 136 if (value != null) 137 BridJ.writeToNative((NativeObject)value); 138 continue; 139 } 140 Pointer ptr = struct.peer.offset(fd.byteOffset); 141 Type tpe = fd.isNativeObject || fd.isArray ? fd.nativeTypeOrPointerTargetType : fd.field.getGenericType(); 142 ptr = ptr.as(tpe); 143 ptr = fixIntegralTypeIOToMatchLength(ptr, fd.byteLength, fd.arrayLength); 144 145 if (fd.isCLong && CLong.SIZE == 4 || fd.isSizeT && SizeT.SIZE == 4) 146 value = (int)(long)(Long)value; 147 148 ptr.set(value); 149 } 150 } catch (Throwable th) { 151 throw new RuntimeException("Unexpected error while writing fields from struct " + Utils.toString(desc.structType) + " (" + getPointer(struct) + ")", th); 152 } 153 } 154 155 /** 156 * Read struct fields implemented as Java fields from the corresponding native memory (Java fields are read from native memory).<br> 157 * This does not concern normal structs as generated by JNAerator (which use getters and setters methods that read and write the fields directly from / to the native memory), but rather structs that are in the JNA style. 158 */ 159 public final void readFieldsFromNative(StructObject struct) { 160 desc.build(); 161 if (!desc.hasFieldFields) 162 return; 163 try { 164 for (StructFieldDescription fd : desc.fields) { 165 if (fd.field == null) 166 continue; 167 168 Pointer ptr = struct.peer.offset(fd.byteOffset); 169 Type tpe = fd.isNativeObject || fd.isArray ? fd.nativeTypeOrPointerTargetType : fd.field.getGenericType(); 170 ptr = ptr.as(tpe); 171 ptr = fixIntegralTypeIOToMatchLength(ptr, fd.byteLength, fd.arrayLength); 172 Object value; 173 if (fd.isArray) { 174 ptr = ptr.validElements(fd.arrayLength); 175 value = ptr; 176 } else { 177 value = ptr.get(); 178 } 179 fd.field.set(struct, value); 180 181 if (value instanceof NativeObject) {//if (fd.isNativeObject) { 182 if (value != null) 183 BridJ.readFromNative((NativeObject)value); 184 } 185 } 186 } catch (Throwable th) { 187 throw new RuntimeException("Unexpected error while reading fields from struct " + Utils.toString(desc.structType) + " (" + getPointer(struct) + ") : " + th, th); 188 } 189 } 190 public final <T> Pointer<T> getPointerField(StructObject struct, int fieldIndex) { 191 StructFieldDescription fd = desc.fields[fieldIndex]; 192 Pointer<T> p; 193 if (fd.isArray) { 194 p = struct.peer.offset(fd.byteOffset).as(fd.nativeTypeOrPointerTargetType); 195 p = p.validElements(fd.arrayLength); 196 } else { 197 p = struct.peer.getPointerAtOffset(fd.byteOffset, fd.nativeTypeOrPointerTargetType); 198 } 199 return p; 200 } 201 202 public final <T> void setPointerField(StructObject struct, int fieldIndex, Pointer<T> value) { 203 StructFieldDescription fd = desc.fields[fieldIndex]; 204 struct.peer.setPointerAtOffset(fd.byteOffset, value); 205 } 206 207 public final <T extends TypedPointer> T getTypedPointerField(StructObject struct, int fieldIndex) { 208 StructFieldDescription fd = desc.fields[fieldIndex]; 209 PointerIO<T> pio = PointerIO.getInstance(fd.nativeTypeOrPointerTargetType); 210 return pio.castTarget(struct.peer.getSizeTAtOffset(fd.byteOffset)); 211 } 212 public final <O extends NativeObject> O getNativeObjectField(StructObject struct, int fieldIndex) { 213 StructFieldDescription fd = desc.fields[fieldIndex]; 214 return (O)struct.peer.offset(fd.byteOffset).getNativeObject(fd.nativeTypeOrPointerTargetType); 215 } 216 217 public final <O extends NativeObject> void setNativeObjectField(StructObject struct, int fieldIndex, O value) { 218 StructFieldDescription fd = desc.fields[fieldIndex]; 219 struct.peer.offset(fd.byteOffset).setNativeObject(value, fd.nativeTypeOrPointerTargetType); 220 } 221 222 public final <E extends Enum<E>> IntValuedEnum<E> getEnumField(StructObject struct, int fieldIndex) { 223 StructFieldDescription fd = desc.fields[fieldIndex]; 224 return FlagSet.fromValue(struct.peer.getIntAtOffset(fd.byteOffset), (Class<E>)fd.nativeTypeOrPointerTargetType); 225 } 226 227 public final void setEnumField(StructObject struct, int fieldIndex, ValuedEnum<?> value) { 228 StructFieldDescription fd = desc.fields[fieldIndex]; 229 struct.peer.setIntAtOffset(fd.byteOffset, (int)value.value()); 230 } 231 232 private void setSignedIntegral(Pointer<?> ptr, long byteOffset, long byteLength, long bitMask, long bitOffset, long value) { 233 if (bitMask != -1) { 234 long previous = ptr.getSignedIntegralAtOffset(byteOffset, byteLength); 235 value = value << bitOffset; 236 value = previous & ~bitMask | value & bitMask; 237 } 238 ptr.setSignedIntegralAtOffset(byteOffset, value, byteLength); 239 } 240 241 public final void setIntField(StructObject struct, int fieldIndex, int value) { 242 StructFieldDescription fd = desc.fields[fieldIndex]; 243 if (4 != fd.byteLength || fd.bitMask != -1) 244 setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value); 245 else 246 struct.peer.setIntAtOffset(fd.byteOffset, value); 247 } 248 public final int getIntField(StructObject struct, int fieldIndex) { 249 StructFieldDescription fd = desc.fields[fieldIndex]; 250 int value; 251 if (4 != fd.byteLength) 252 value = (int)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength); 253 else 254 value = struct.peer.getIntAtOffset(fd.byteOffset); 255 256 return (int) ((value & fd.bitMask) >> fd.bitOffset); 257 } 258 public final void setLongField(StructObject struct, int fieldIndex, long value) { 259 StructFieldDescription fd = desc.fields[fieldIndex]; 260 if (8 != fd.byteLength || fd.bitMask != -1) 261 setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value); 262 else 263 struct.peer.setLongAtOffset(fd.byteOffset, value); 264 } 265 public final long getLongField(StructObject struct, int fieldIndex) { 266 StructFieldDescription fd = desc.fields[fieldIndex]; 267 long value; 268 if (8 != fd.byteLength) 269 value = (long)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength); 270 else 271 value = struct.peer.getLongAtOffset(fd.byteOffset); 272 273 return (long) ((value & fd.bitMask) >> fd.bitOffset); 274 } 275 public final void setShortField(StructObject struct, int fieldIndex, short value) { 276 StructFieldDescription fd = desc.fields[fieldIndex]; 277 if (2 != fd.byteLength || fd.bitMask != -1) 278 setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value); 279 else 280 struct.peer.setShortAtOffset(fd.byteOffset, value); 281 } 282 public final short getShortField(StructObject struct, int fieldIndex) { 283 StructFieldDescription fd = desc.fields[fieldIndex]; 284 short value; 285 if (2 != fd.byteLength) 286 value = (short)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength); 287 else 288 value = struct.peer.getShortAtOffset(fd.byteOffset); 289 290 return (short) ((value & fd.bitMask) >> fd.bitOffset); 291 } 292 public final void setByteField(StructObject struct, int fieldIndex, byte value) { 293 StructFieldDescription fd = desc.fields[fieldIndex]; 294 if (1 != fd.byteLength || fd.bitMask != -1) 295 setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value); 296 else 297 struct.peer.setByteAtOffset(fd.byteOffset, value); 298 } 299 public final byte getByteField(StructObject struct, int fieldIndex) { 300 StructFieldDescription fd = desc.fields[fieldIndex]; 301 byte value; 302 if (1 != fd.byteLength) 303 value = (byte)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength); 304 else 305 value = struct.peer.getByteAtOffset(fd.byteOffset); 306 307 return (byte) ((value & fd.bitMask) >> fd.bitOffset); 308 } 309 public final void setCharField(StructObject struct, int fieldIndex, char value) { 310 StructFieldDescription fd = desc.fields[fieldIndex]; 311 struct.peer.setCharAtOffset(fd.byteOffset, value); 312 } 313 public final char getCharField(StructObject struct, int fieldIndex) { 314 StructFieldDescription fd = desc.fields[fieldIndex]; 315 char value; 316 value = struct.peer.getCharAtOffset(fd.byteOffset); 317 318 //assert fd.bitMask == -1; 319 return value; 320 } 321 public final void setFloatField(StructObject struct, int fieldIndex, float value) { 322 StructFieldDescription fd = desc.fields[fieldIndex]; 323 struct.peer.setFloatAtOffset(fd.byteOffset, value); 324 } 325 public final float getFloatField(StructObject struct, int fieldIndex) { 326 StructFieldDescription fd = desc.fields[fieldIndex]; 327 float value; 328 value = struct.peer.getFloatAtOffset(fd.byteOffset); 329 330 //assert fd.bitMask == -1; 331 return value; 332 } 333 public final void setDoubleField(StructObject struct, int fieldIndex, double value) { 334 StructFieldDescription fd = desc.fields[fieldIndex]; 335 struct.peer.setDoubleAtOffset(fd.byteOffset, value); 336 } 337 public final double getDoubleField(StructObject struct, int fieldIndex) { 338 StructFieldDescription fd = desc.fields[fieldIndex]; 339 double value; 340 value = struct.peer.getDoubleAtOffset(fd.byteOffset); 341 342 //assert fd.bitMask == -1; 343 return value; 344 } 345 public final void setBooleanField(StructObject struct, int fieldIndex, boolean value) { 346 StructFieldDescription fd = desc.fields[fieldIndex]; 347 struct.peer.setBooleanAtOffset(fd.byteOffset, value); 348 } 349 public final boolean getBooleanField(StructObject struct, int fieldIndex) { 350 StructFieldDescription fd = desc.fields[fieldIndex]; 351 boolean value; 352 value = struct.peer.getBooleanAtOffset(fd.byteOffset); 353 354 //assert fd.bitMask == -1; 355 return value; 356 } 357 358 public final void setSizeTField(StructObject struct, int fieldIndex, long value) { 359 StructFieldDescription fd = desc.fields[fieldIndex]; 360 struct.peer.setSizeTAtOffset(fd.byteOffset, value); 361 } 362 public final long getSizeTField(StructObject struct, int fieldIndex) { 363 StructFieldDescription fd = desc.fields[fieldIndex]; 364 return struct.peer.getSizeTAtOffset(fd.byteOffset); 365 } 366 public final void setCLongField(StructObject struct, int fieldIndex, long value) { 367 StructFieldDescription fd = desc.fields[fieldIndex]; 368 struct.peer.setCLongAtOffset(fd.byteOffset, value); 369 } 370 public final long getCLongField(StructObject struct, int fieldIndex) { 371 StructFieldDescription fd = desc.fields[fieldIndex]; 372 return struct.peer.getCLongAtOffset(fd.byteOffset); 373 } 374 375 public final void setTimeTField(StructObject struct, int fieldIndex, TimeT value) { 376 StructFieldDescription fd = desc.fields[fieldIndex]; 377 struct.peer.setIntegralAtOffset(fd.byteOffset, value); 378 } 379 public final TimeT getTimeTField(StructObject struct, int fieldIndex) { 380 StructFieldDescription fd = desc.fields[fieldIndex]; 381 return new TimeT(struct.peer.getIntegralAtOffset(fd.byteOffset, TimeT.SIZE)); 382 } 383}