public int getPositionInVirtualTable( Pointer<Pointer<?>> pVirtualTable, Method method, NativeLibrary library) { // Pointer<?> typeInfo = pVirtualTable.get(1); int methodsOffset = 0; // library.isMSVC() ? 0 : -2;///2; String className = getCPPClassName(method.getDeclaringClass()); for (int iVirtual = 0; ; iVirtual++) { Pointer<?> pMethod = pVirtualTable.get(methodsOffset + iVirtual); String virtualMethodName = pMethod == null ? null : library.getSymbolName(pMethod.getPeer()); // System.out.println("#\n# At index " + methodsOffset + " + " + iVirtual + " of vptr for // class " + className + ", found symbol " + Long.toHexString(pMethod.getPeer()) + " = '" + // virtualMethodName + "'\n#"); if (virtualMethodName == null) { if (debug) info("\tVtable(" + className + ")[" + iVirtual + "] = null"); return -1; } try { MemberRef mr = library.parseSymbol(virtualMethodName); if (debug) info("\tVtable(" + className + ")[" + iVirtual + "] = " + virtualMethodName + " = " + mr); if (mr != null && mr.matchesSignature(method)) return iVirtual; else if (library.isMSVC() && !mr.matchesEnclosingType(method)) break; // no NULL terminator in MSVC++ vtables, so we have to guess when we've reached the // end } catch (Demangler.DemanglingException ex) { BridJ.warning( "Failed to demangle '" + virtualMethodName + "' during inspection of virtual table for '" + method.toGenericString() + "' : " + ex); } } return -1; }
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; }
public MemoryOperators(NativeLibrary library) { for (Symbol sym : library.getSymbols()) { try { MemberRef parsedRef = sym.getParsedRef(); IdentLike n = parsedRef.getMemberName(); if (SpecialName.New.equals(n)) newFct = pointerToAddress(sym.getAddress()) .asDynamicFunction(null, Pointer.class, SizeT.class); else if (SpecialName.NewArray.equals(n)) newFct = pointerToAddress(sym.getAddress()) .asDynamicFunction(null, Pointer.class, SizeT.class); else if (SpecialName.Delete.equals(n)) newFct = pointerToAddress(sym.getAddress()) .asDynamicFunction(null, Void.class, Pointer.class); else if (SpecialName.DeleteArray.equals(n)) newFct = pointerToAddress(sym.getAddress()) .asDynamicFunction(null, Void.class, Pointer.class); } catch (Exception ex) { } } }
synchronized void parse() { if (!refParsed) { try { ref = library.parseSymbol(symbol); } catch (DemanglingException ex) { if (BridJ.debug) { ex.printStackTrace(); } if (BridJ.verbose) { BridJ.warning("Symbol parsing failed : " + ex.getMessage()); } } refParsed = true; } }
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; }
@Override public boolean functionExists(String functionName) { return lib.getSymbol(functionName) != null; }
public long getAddress() { if (address == 0) { address = library.getSymbolAddress(symbol); } return address; }
public static void main(String[] args) throws IOException { try { { JFrame f = new JFrame(); f.setVisible(true); long hwndVal = JAWTUtils.getNativePeerHandle(f); // TODO com.sun.jna.Native.getComponentID(this); System.out.println("#\n# hwndVal = " + hwndVal + "\n#"); BridJ.register(); ValuedEnum<ETest> t = testEnum(ETest.eFirst); if (t != ETest.eFirst) throw new RuntimeException(); } testSetGetIntBuffer(10); // if (Platform.isMacOSX()) { // new NSCalendar(); // new NSAutoReleasePool(); // } // NativeLibrary lib = BridJ.getNativeLibrary("OpenCL", new // File("/System/Library/Frameworks/OpenCL.framework/OpenCL")); // NativeLibrary lib = BridJ.getNativeLibrary("OpenCL", new // File("/usr/lib/libobjc.dylib")); // NativeLibrary lib = BridJ.getNativeLibrary("OpenCL", new // File("/Users/ochafik/nativelibs4java/Runtime/BridJ/src/test/cpp/test/build_out/darwin_universal_gcc_debug/libtest.dylib")); // Collection<Symbol> symbols = lib.getSymbols(); BridJ.register(MyCallback.class); BridJ.register(); int ra = testAddDyncall(10, 4); if (ra != 14) throw new RuntimeException("Expected 14, got " + ra); ra = testAddDyncall(10, 4); if (ra != 14) throw new RuntimeException("Expected 14, got " + ra); testNativeTargetCallbacks(); testJavaTargetCallbacks(); if (true) return; long crea = Ctest.createTest(); crea = Pointer.pointerToAddress(crea).getPointer().getPeer(); print("Ctest.createTest()", crea, 10, 0); Ctest test = new Ctest(); // long thisPtr = test.$this.getPeer(); // System.out.println(hex(thisPtr)); print("Ctest.this", Pointer.pointerTo(test, Ctest.class).getPointer().getPeer(), 10, 2); int res = test.testAdd(1, 2); System.out.println("res = " + res); res = test.testVirtualAdd(1, 2); System.out.println("res = " + res); res = test.testVirtualAddStdCall(null, 1, 2); System.out.println("res = " + res); res = test.testAddStdCall(null, 1, 2); System.out.println("res = " + res); TaskbarListDemo.main(null); IShellWindows win = COMRuntime.newInstance(IShellWindows.class); IUnknown iu = win.QueryInterface(IUnknown.class); if (iu == null) throw new RuntimeException("Interface does not handle IUnknown !"); win.Release(); try { new FunctionTest().add(); MyStruct s = new MyStruct(); s.a(10); System.out.println("Created MyStruct and set it to 10"); int a = Pointer.pointerTo(s).getInt(); a = s.a(); Pointer.pointerTo(s).setInt(10); a = Pointer.pointerTo(s).getInt(); a = s.a(); if (s.a() != 10) throw new RuntimeException("invalid value = " + a); s.b(100.0); if (s.b() != 100.0) throw new RuntimeException("invalid value = " + a); } catch (Throwable ex) { ex.printStackTrace(); } library = BridJ.getNativeLibrary("test"); // NativeLibrary.load(libraryPath); new VC9Demangler(null, "?sinInt@@YANH@Z").parseSymbol(); new VC9Demangler(null, "?forwardCall@@YAHP6AHHH@ZHH@Z").parseSymbol(); BridJ.register(); // new VC9Demangler(null, "??0Ctest2@@QEAA@XZ").parseSymbol(); for (Demangler.Symbol symbol : library.getSymbols()) { String name = symbol.getName(); long addr = symbol.getAddress(); System.out.println(name + " = \t" + hex(addr)); if (name.startsWith("_ZTV") || name.startsWith("_ZTI") || name.startsWith("??_")) { print("vtable", addr, 10, 1); } else System.out.println("'" + name + "'"); } boolean is64 = Platform.is64Bits(); } catch (Throwable ex) { ex.printStackTrace(); } finally { System.in.read(); } /*double dres = PerfLib.testASinB(1, 2); res = PerfLib.testAddJNI(1, 2); System.out.println("Done");*/ }
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; }
private String ptrToString(Pointer<?> ptr, NativeLibrary library) { return ptr == null ? "null" : Long.toHexString(ptr.getPeer()) + " (" + library.getSymbolName(ptr.getPeer()) + ")"; }
@Override protected void registerNativeMethod( Class<?> type, NativeLibrary typeLibrary, Method method, NativeLibrary methodLibrary, Builder builder, MethodCallInfoBuilder methodCallInfoBuilder) throws FileNotFoundException { int modifiers = method.getModifiers(); boolean isCPPClass = CPPObject.class.isAssignableFrom(method.getDeclaringClass()); // Annotation[][] anns = method.getParameterAnnotations(); if (!isCPPClass) { super.registerNativeMethod( type, typeLibrary, method, methodLibrary, builder, methodCallInfoBuilder); return; } MethodCallInfo mci = methodCallInfoBuilder.apply(method); Virtual va = method.getAnnotation(Virtual.class); if (va == null) { Symbol symbol = methodLibrary.getSymbol(method); mci.setForwardedPointer(symbol == null ? 0 : symbol.getAddress()); if (mci.getForwardedPointer() == 0) { assert error( "Method " + method.toGenericString() + " is not virtual but its address could not be resolved in the library."); return; } if (Modifier.isStatic(modifiers)) { builder.addFunction(mci); if (debug) info("Registering " + method + " as function or static C++ method " + symbol.getName()); } else { builder.addFunction(mci); if (debug) info("Registering " + method + " as C++ method " + symbol.getName()); } } else { if (Modifier.isStatic(modifiers)) { warning( "Method " + method.toGenericString() + " is native and maps to a function, but is not static."); } int theoreticalVirtualIndex = va.value(); int theoreticalAbsoluteVirtualIndex = theoreticalVirtualIndex < 0 ? -1 : getAbsoluteVirtualIndex(method, theoreticalVirtualIndex, type); int absoluteVirtualIndex; Pointer<Pointer<?>> pVirtualTable = isCPPClass && typeLibrary != null ? (Pointer) pointerToAddress(getVirtualTable(type, typeLibrary), Pointer.class) : null; if (pVirtualTable == null) { if (theoreticalAbsoluteVirtualIndex < 0) { error( "Method " + method.toGenericString() + " is virtual but the virtual table of class " + type.getName() + " was not found and the virtual method index is not provided in its @Virtual annotation."); return; } absoluteVirtualIndex = theoreticalAbsoluteVirtualIndex; } else { int guessedAbsoluteVirtualIndex = getPositionInVirtualTable(pVirtualTable, method, typeLibrary); if (guessedAbsoluteVirtualIndex < 0) { if (theoreticalAbsoluteVirtualIndex < 0) { error( "Method " + method.toGenericString() + " is virtual but its position could not be found in the virtual table."); return; } else { absoluteVirtualIndex = theoreticalAbsoluteVirtualIndex; } } else { if (theoreticalAbsoluteVirtualIndex >= 0 && guessedAbsoluteVirtualIndex != theoreticalAbsoluteVirtualIndex) { warning( "Method " + method.toGenericString() + " has @Virtual annotation indicating virtual index " + theoreticalAbsoluteVirtualIndex + ", but analysis of the actual virtual table rather indicates it has index " + guessedAbsoluteVirtualIndex + " (using the guess)"); } absoluteVirtualIndex = guessedAbsoluteVirtualIndex; } } mci.setVirtualIndex(absoluteVirtualIndex); if (debug) info( "Registering " + method.toGenericString() + " as virtual C++ method with absolute virtual table index = " + absoluteVirtualIndex); builder.addVirtualMethod(mci); } }
private org.bridj.Pointer<?> f(String prefix, String functionName) { final String fullname = (prefix == null ? "" : prefix + sep) + functionName; return library.getSymbolPointer(fullname); }