long getVirtualTable(Type type, NativeLibrary library) { Long vtable = vtables.get(type); if (vtable == null) { final Class<?> typeClass = Utils.getClass(type); if (false) { String className = typeClass.getSimpleName(); String vtableSymbol; if (Platform.isWindows()) vtableSymbol = "??_7" + className + "@@6B@"; else vtableSymbol = "_ZTV" + className.length() + className; vtables.put(type, vtable = library.getSymbolAddress(vtableSymbol)); } else { Symbol symbol = library.getFirstMatchingSymbol( new SymbolAccepter() { public boolean accept(Symbol symbol) { return symbol.matchesVirtualTable(typeClass); } }); if (symbol != null) { if (BridJ.debug) info("Registering vtable of " + Utils.toString(type) + " as " + symbol.getName()); // Pointer<Pointer> pp = pointerToAddress(symbol.getAddress(), // Pointer.class); // // for (int i = 0; i < 6; i++) { // Pointer p = pp.get(i); //// if (p == null) //// break; // String n = p == null ? null : // library.getSymbolName(p.getPeer()); // info("\tVtable entry " + i + " = " + p + " (" + n + ")"); //// if (n == null) //// break; // } } else if (getVirtualMethodsCount(typeClass) > 0) error("Failed to find a vtable for type " + Utils.toString(type)); if (symbol != null) { long address = symbol.getAddress(); vtable = library.isMSVC() ? address : address + 2 * Pointer.SIZE; } else { vtable = 0L; } vtables.put(type, vtable); // */ } } return vtable; }
Pointer.Releaser newCPPReleaser(final Type type) { try { final Class<?> typeClass = Utils.getClass(type); NativeLibrary lib = BridJ.getNativeLibrary(typeClass); return newCPPReleaser(type, typeClass, lib); } catch (Throwable th) { throw new RuntimeException( "Failed to create a C++ destructor for type " + Utils.toString(type) + " : " + th, th); } }
protected boolean installSyntheticVTablePtr(Type type, NativeLibrary library, Pointer<?> peer) { synchronized (syntheticVirtualTables) { VTable vtable = syntheticVirtualTables.get(type); if (vtable == null) { if (!typesThatDontNeedASyntheticVirtualTable.contains(type)) { List<VirtMeth> methods = new ArrayList<VirtMeth>(); listVirtualMethods(Utils.getClass(type), methods); boolean needsASyntheticVirtualTable = false; for (VirtMeth method : methods) if (!Modifier.isNative(method.implementation.getModifiers())) { needsASyntheticVirtualTable = true; break; } if (needsASyntheticVirtualTable) { Type parentType = Utils.getParent(type); Pointer<Pointer> parentVTablePtr = null; if (CPPObject.class.isAssignableFrom(Utils.getClass(parentType))) { parentVTablePtr = peer.getPointer(Pointer.class); if (BridJ.debug) { BridJ.info( "Found parent virtual table pointer = " + ptrToString(parentVTablePtr, library)); /*Pointer<Pointer> expectedParentVTablePtr = pointerToAddress(getVirtualTable(parentType, library), Pointer.class); if (expectedParentVTablePtr != null && !Utils.eq(parentVTablePtr, expectedParentVTablePtr)) BridJ.warning("Weird parent virtual table pointer : expected " + ptrToString(expectedParentVTablePtr, library) + ", got " + ptrToString(parentVTablePtr, library)); */ } // parentVTablePtr = pointerToAddress(getVirtualTable(parentType, library), // Pointer.class); } syntheticVirtualTables.put( type, vtable = synthetizeVirtualTable(type, parentVTablePtr, methods, library)); } else { typesThatDontNeedASyntheticVirtualTable.add(type); } } } if (vtable != null) { if (BridJ.debug) BridJ.info( "Installing synthetic vtable pointer " + vtable.ptr + " to instance at " + peer + " (type = " + Utils.toString(type) + ", " + vtable.callbacks.size() + " callbacks)"); peer.setPointer(vtable.ptr); return vtable.ptr != null; } else return false; } }
@Override public T createReturnInstance() { try { Object[] templateParameters = getTemplateParameters(type); T instance = (T) getCastClass().newInstance(); initialize(instance, SKIP_CONSTRUCTOR, templateParameters); // setTemplateParameters(instance, typeClass, getTemplateParameters(type)); return instance; } catch (Throwable th) { throw new RuntimeException( "Failed to create a return instance for type " + Utils.toString(type) + " : " + th, th); } }
protected boolean installRegularVTablePtr(Type type, NativeLibrary library, Pointer<?> peer) { long vtablePtr = getVirtualTable(type, library); if (vtablePtr != 0) { if (BridJ.debug) BridJ.info( "Installing regular vtable pointer " + Pointer.pointerToAddress(vtablePtr) + " to instance at " + peer + " (type = " + Utils.toString(type) + ")"); peer.setSizeT(vtablePtr); return true; } return false; }
CPPDestructor getDestructor(final Class<?> typeClass, Type type, NativeLibrary lib) { CPPDestructor destructor = destructors.get(type); if (destructor == null) { Symbol symbol = lib.getFirstMatchingSymbol( new SymbolAccepter() { public boolean accept(Symbol symbol) { return symbol.matchesDestructor(typeClass); } }); if (BridJ.debug && symbol != null) info("Registering destructor of " + Utils.toString(type) + " as " + symbol.getName()); if (symbol != null) destructors.put( type, destructor = pointerToAddress(symbol.getAddress(), CPPDestructor.class).get()); } return destructor; }
public ValueType getValueType( int iParam, int nParams, Class<?> c, Type t, AnnotatedElement element, Annotation... directAnnotations) { boolean isPtr = isAnnotationPresent(Ptr.class, element, directAnnotations); boolean isCLong = isAnnotationPresent(org.bridj.ann.CLong.class, element, directAnnotations); Constructor cons = getAnnotation(Constructor.class, element, directAnnotations); if (isPtr || cons != null || isCLong) { if (!(c == Long.class || c == Long.TYPE)) throw new RuntimeException( "Annotation should only be used on a long parameter, not on a " + c.getName()); if (isPtr) { if (!Platform.is64Bits()) direct = false; } else if (isCLong) { if (Platform.CLONG_SIZE != 8) direct = false; } else if (cons != null) { isCPlusPlus = true; startsWithThis = true; if (iParam != 0) throw new RuntimeException( "Annotation " + Constructor.class.getName() + " cannot have more than one (long) argument"); } return ValueType.eSizeTValue; } if (c == null || c.equals(Void.TYPE)) return ValueType.eVoidValue; if (c == Integer.class || c == Integer.TYPE) return ValueType.eIntValue; if (c == Long.class || c == Long.TYPE) { return !isPtr || Platform.is64Bits() ? ValueType.eLongValue : ValueType.eIntValue; } if (c == Short.class || c == Short.TYPE) return ValueType.eShortValue; if (c == Byte.class || c == Byte.TYPE) return ValueType.eByteValue; if (c == Boolean.class || c == Boolean.TYPE) return ValueType.eBooleanValue; if (c == Float.class || c == Float.TYPE) { usesFloats(); return ValueType.eFloatValue; } if (c == char.class || c == Character.TYPE) { if (Platform.WCHAR_T_SIZE != 2) direct = false; return ValueType.eWCharValue; } if (c == Double.class || c == Double.TYPE) { usesFloats(); return ValueType.eDoubleValue; } if (c == CLong.class) { direct = false; return ValueType.eCLongObjectValue; } if (c == SizeT.class) { direct = false; return ValueType.eSizeTObjectValue; } if (c == TimeT.class) { direct = false; return ValueType.eTimeTObjectValue; } if (Pointer.class.isAssignableFrom(c)) { direct = false; CallIO cio = CallIO.Utils.createPointerCallIO(c, t); if (BridJ.veryVerbose) BridJ.info("CallIO : " + cio); addCallIO(cio); return ValueType.ePointerValue; } if (c.isArray() && iParam == nParams - 1) { direct = false; return ValueType.eEllipsis; } if (ValuedEnum.class.isAssignableFrom(c)) { direct = false; CallIO cio = CallIO.Utils.createValuedEnumCallIO( (Class) Utils.getClass(Utils.getUniqueParameterizedTypeParameter(t))); if (BridJ.veryVerbose) BridJ.info("CallIO : " + cio); addCallIO(cio); return ValueType.eIntFlagSet; } if (NativeObject.class.isAssignableFrom(c)) { Pointer<DCstruct> pStruct = null; if (StructObject.class.isAssignableFrom(c)) { StructIO io = StructIO.getInstance(c, t); try { pStruct = DyncallStructs.buildDCstruct(io.desc); } catch (Throwable th) { BridJ.error( "Unable to create low-level struct metadata for " + Utils.toString(t) + " : won't be able to use it as a by-value function argument.", th); } } addCallIO(new CallIO.NativeObjectHandler((Class<? extends NativeObject>) c, t, pStruct)); direct = false; return ValueType.eNativeObjectValue; } throw new NoSuchElementException( "No " + ValueType.class.getSimpleName() + " for class " + c.getName()); }
DynamicFunction getConstructor( final Class<?> typeClass, final Type type, NativeLibrary lib, int constructorId) { Pair<Type, Integer> key = new Pair<Type, Integer>(type, constructorId); DynamicFunction constructor = constructors.get(key); if (constructor == null) { try { final Constructor<?> constr; try { constr = findConstructor(typeClass, constructorId, true); if (debug) BridJ.info("Found constructor for " + Utils.toString(type) + " : " + constr); } catch (NoSuchMethodException ex) { if (debug) BridJ.info("No constructor for " + Utils.toString(type)); return null; } Symbol symbol = lib == null ? null : lib.getFirstMatchingSymbol( new SymbolAccepter() { public boolean accept(Symbol symbol) { return symbol.matchesConstructor( constr.getDeclaringClass() == Utils.getClass(type) ? type : constr.getDeclaringClass() /* TODO */, constr); } }); if (symbol == null) { if (debug) BridJ.info("No matching constructor for " + Utils.toString(type) + " (" + constr + ")"); return null; } if (debug) info("Registering constructor " + constr + " as " + symbol.getName()); // TODO do something with these args ! int templateParametersCount = getTemplateParametersCount(typeClass); Class<?>[] consParamTypes = constr.getParameterTypes(); Class<?>[] consThisParamTypes = new Class[consParamTypes.length + 1 - templateParametersCount]; consThisParamTypes[0] = Pointer.class; System.arraycopy( consParamTypes, templateParametersCount, consThisParamTypes, 1, consParamTypes.length - templateParametersCount); DynamicFunctionFactory constructorFactory = getDynamicFunctionFactory(lib, Style.ThisCall, void.class, consThisParamTypes); constructor = constructorFactory.newInstance(pointerToAddress(symbol.getAddress())); constructors.put(key, constructor); } catch (Throwable th) { th.printStackTrace(); throw new RuntimeException( "Unable to create constructor " + constructorId + " for " + type + " : " + th, th); } } return constructor; }