java-gobject-introspection r19 - in trunk/src/org/gnome/gir: compiler gobject



Author: walters
Date: Wed Sep  3 01:55:46 2008
New Revision: 19
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=19&view=rev

Log:
Handle return interfaces with no known native proxy by creating Stub


Modified:
   trunk/src/org/gnome/gir/compiler/CodeFactory.java
   trunk/src/org/gnome/gir/compiler/Test.java
   trunk/src/org/gnome/gir/gobject/GObject.java
   trunk/src/org/gnome/gir/gobject/GTypeMapper.java
   trunk/src/org/gnome/gir/gobject/NativeObject.java

Modified: trunk/src/org/gnome/gir/compiler/CodeFactory.java
==============================================================================
--- trunk/src/org/gnome/gir/compiler/CodeFactory.java	(original)
+++ trunk/src/org/gnome/gir/compiler/CodeFactory.java	Wed Sep  3 01:55:46 2008
@@ -884,9 +884,27 @@
 		
 		sigCompilation.writer.visitEnd();
 	}
+	
+	private void writeHandleInitializer(ClassCompilation compilation, String parentInternalName) {
+		MethodVisitor mv = compilation.writer.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/gnome/gir/gobject/Handle$Initializer;)V", null, null);
+		mv.visitCode();
+		Label l0 = new Label();
+		mv.visitLabel(l0);
+		mv.visitVarInsn(ALOAD, 0);
+		mv.visitVarInsn(ALOAD, 1);
+		mv.visitMethodInsn(INVOKESPECIAL, parentInternalName, "<init>", "(Lorg/gnome/gir/gobject/Handle$Initializer;)V");
+		Label l1 = new Label();
+		mv.visitLabel(l1);
+		mv.visitInsn(RETURN);
+		Label l2 = new Label();
+		mv.visitLabel(l2);
+		mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l2, 0);
+		mv.visitLocalVariable("init", "Lorg/gnome/gir/gobject/Handle$Initializer;", null, l0, l2, 1);
+		mv.visitMaxs(2, 2);
+		mv.visitEnd();	
+	}
 		
 	private void compile(ObjectInfo info) {
-		Label l0, l1, l2;
 		StubClassCompilation compilation = getCompilation(info);
 		
 		if (info.getNamespace().equals("GObject") && info.getName().equals("Object"))
@@ -921,22 +939,7 @@
 		
 		writeGetGType(info, compilation);
 		
-		MethodVisitor mv = compilation.writer.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/gnome/gir/gobject/Handle$Initializer;)V", null, null);
-		mv.visitCode();
-		l0 = new Label();
-		mv.visitLabel(l0);
-		mv.visitVarInsn(ALOAD, 0);
-		mv.visitVarInsn(ALOAD, 1);
-		mv.visitMethodInsn(INVOKESPECIAL, parentInternalName, "<init>", "(Lorg/gnome/gir/gobject/Handle$Initializer;)V");
-		l1 = new Label();
-		mv.visitLabel(l1);
-		mv.visitInsn(RETURN);
-		l2 = new Label();
-		mv.visitLabel(l2);
-		mv.visitLocalVariable("this", "L" + internalName + ";", null, l0, l2, 0);
-		mv.visitLocalVariable("init", "Lorg/gnome/gir/gobject/Handle$Initializer;", null, l0, l2, 1);
-		mv.visitMaxs(2, 2);
-		mv.visitEnd();	
+		writeHandleInitializer(compilation, parentInternalName);
 		
 		compileDefaultConstructor(info, compilation);
 		
@@ -985,7 +988,7 @@
 			CallableCompilationContext ctx = tryCompileCallable(fi, sigs);
 			if (ctx == null)
 				continue;			
-			writeCallable(ACC_PUBLIC, info, compilation, fi, ctx);
+			writeCallable(ACC_PUBLIC, compilation, fi, ctx);
 		}
 		for (InterfaceInfo iface : giInterfaces) {
 			for (FunctionInfo fi: iface.getMethods()) {
@@ -994,7 +997,7 @@
 					continue;
 				ctx.isInterfaceMethod = true;
 				ctx.targetInterface = iface;
-				writeCallable(ACC_PUBLIC, info, compilation, fi, ctx);
+				writeCallable(ACC_PUBLIC, compilation, fi, ctx);
 			}
 		}
 		compilation.close();	
@@ -1005,7 +1008,8 @@
 		
 		String internalName = getInternalName(info);
 		
-		compilation.writer.visit(V1_6, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, internalName, null, "java/lang/Object", null);
+		compilation.writer.visit(V1_6, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, internalName, null, "java/lang/Object", 
+				new String[] { "org/gnome/gir/gobject/GObject$GObjectProxy" });
 		Set<String> sigs = new HashSet<String>();		
 		for (FunctionInfo fi : info.getMethods()) {
 			CallableCompilationContext ctx = tryCompileCallable(fi, sigs);
@@ -1017,6 +1021,22 @@
 			mv.visitEnd();			
 		}
 
+		InnerClassCompilation anonProxy = compilation.newInner("AnonStub");
+		compilation.writer.visitInnerClass(anonProxy.internalName,
+				compilation.internalName, "AnonStub", ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
+		anonProxy.writer.visit(V1_6, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, anonProxy.internalName, null, "org/gnome/gir/gobject/GObject", 
+				new String[] { compilation.internalName });
+		writeHandleInitializer(anonProxy, "org/gnome/gir/gobject/GObject");
+		sigs = new HashSet<String>();		
+		for (FunctionInfo fi: info.getMethods()) {
+			CallableCompilationContext ctx = tryCompileCallable(fi, sigs);
+			if (ctx == null)
+				continue;
+			ctx.isInterfaceMethod = false;
+			ctx.targetInterface = info;
+			writeCallable(ACC_PUBLIC, anonProxy, fi, ctx);
+		}		
+	
 		compilation.close();
 	}
 	
@@ -1086,8 +1106,7 @@
 		return new CallableCompilationContext(returnType, argInfos, args, throwsGError);
 	}
 	
-	private void writeCallable(int accessFlags,
-			RegisteredTypeInfo parent, ClassCompilation compilation, FunctionInfo fi,
+	private void writeCallable(int accessFlags, ClassCompilation compilation, FunctionInfo fi,
 			CallableCompilationContext ctx) {
 		String descriptor = Type.getMethodDescriptor(ctx.returnType, ctx.argTypes.toArray(new Type[0]));
 		String name = ucaseToCamel(fi.getName());
@@ -1216,6 +1235,7 @@
 			mv.visitLocalVariable("result", "L" + ctx.returnType.getInternalName() + ";", null, l2, l4, resultOffset);
 		}
 		mv.visitMaxs(8, errorOffset+1);
+		mv.visitEnd();
 	}
 
 	private void writeGetGType(RegisteredTypeInfo rti, ClassCompilation compilation) {
@@ -1243,7 +1263,7 @@
 		CallableCompilationContext ctx = tryCompileCallable(fi, globalSigs);
 		if (ctx == null)
 			return;	
-		writeCallable(ACC_PUBLIC + ACC_STATIC + ACC_FINAL, null, compilation, fi, ctx);
+		writeCallable(ACC_PUBLIC + ACC_STATIC + ACC_FINAL, compilation, fi, ctx);
 	}
 	
 	private void compile(StructInfo info) {
@@ -1284,7 +1304,7 @@
 			CallableCompilationContext ctx = tryCompileCallable(fi, sigs);
 			if (ctx == null)
 				continue;			
-			writeCallable(ACC_PUBLIC, info, compilation, fi, ctx);	
+			writeCallable(ACC_PUBLIC, compilation, fi, ctx);	
 		}
 		
 		for (FieldInfo fi : info.getFields()) {

Modified: trunk/src/org/gnome/gir/compiler/Test.java
==============================================================================
--- trunk/src/org/gnome/gir/compiler/Test.java	(original)
+++ trunk/src/org/gnome/gir/compiler/Test.java	Wed Sep  3 01:55:46 2008
@@ -36,11 +36,11 @@
 		PointerByReference error = new PointerByReference(null);
 		Function target = Internals.library.getFunction("glib_baz");
 		Object[] args = new Object[] { x, z };
-		Test result = (Test) target.invoke(Integer.class, args, Internals.invocationOptions); 
+		Pointer result = (Pointer) target.invoke(Pointer.class, args, Internals.invocationOptions); 
 		if (result == null) {
 			throw new GErrorException(new GErrorStruct(error.getValue()));
 		}		
-		return result;
+		return (Test) objectFor(result, Test.class);
 	}	
 	
 	public static Test newWithFoo(String blah) {

Modified: trunk/src/org/gnome/gir/gobject/GObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GObject.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GObject.java	Wed Sep  3 01:55:46 2008
@@ -72,6 +72,13 @@
     private Map<String, Map<Closure, ClosureProxy>> signalClosures;
     
     private final IntPtr objectID = new IntPtr(System.identityHashCode(this));
+    
+    /**
+     * A tagging interface used in the code generator - if a method returns an interface,
+     * we have it extend this interface so we know it's a GObject. 
+     * @author walters
+     */
+    public static interface GObjectProxy {};
 
     public GObject(Initializer init) { 
         super(init.needRef ? initializer(init.ptr, false, init.ownsHandle) : init);
@@ -521,6 +528,7 @@
                     if (nativeParam == null) {
                         continue;
                     }
+                 
                     if (NativeObject.class.isAssignableFrom(paramType)) {
                         javaParam = NativeObject.objectFor((Pointer) nativeParam, 
                                 paramType, 1, true);

Modified: trunk/src/org/gnome/gir/gobject/GTypeMapper.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GTypeMapper.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GTypeMapper.java	Wed Sep  3 01:55:46 2008
@@ -274,7 +274,9 @@
     @SuppressWarnings("unchecked")
 	public FromNativeConverter getFromNativeConverter(Class type) {
         if (Enum.class.isAssignableFrom(type)) {
-            return enumConverter;              
+            return enumConverter;
+        } else if (GObject.GObjectProxy.class.isAssignableFrom(type)) {
+            return nativeObjectConverter;            
         } else if (NativeObject.class.isAssignableFrom(type)) {
             return nativeObjectConverter;
         } else if (Boolean.class == type || boolean.class == type) {
@@ -293,6 +295,8 @@
 	public ToNativeConverter getToNativeConverter(Class type) {
         if (NativeObject.class.isAssignableFrom(type)) {
             return nativeObjectConverter;
+        } else if (GObject.GObjectProxy.class.isAssignableFrom(type)) {
+            return nativeObjectConverter;                   
         } else if (NativeValue.class.isAssignableFrom(type)) {
             return nativeValueArgumentConverter;
         } else if (Enum.class.isAssignableFrom(type)) {

Modified: trunk/src/org/gnome/gir/gobject/NativeObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/NativeObject.java	(original)
+++ trunk/src/org/gnome/gir/gobject/NativeObject.java	Wed Sep  3 01:55:46 2008
@@ -168,7 +168,17 @@
         return objectFor(ptr, cls, needRef ? 1 : 0, ownsHandle);
     }
     
-    public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, int refAdjust, boolean ownsHandle) {
+    private static Class<?> getStubClassFor(Class<?> proxyClass) {
+    	Class<?>[] declared = proxyClass.getDeclaredClasses();
+    	for (Class<?> c: declared) {
+    		if (c.getName().endsWith("$AnonStub"))
+    			return c;
+    	}
+    	throw new RuntimeException("Couldn't find Stub for interface: " + proxyClass);
+    }
+    
+    @SuppressWarnings("unchecked")
+	public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, int refAdjust, boolean ownsHandle) {
         // Ignore null pointers
         if (ptr == null) {
             return null;
@@ -184,15 +194,21 @@
             }
             return cls.cast(obj);
         }
-        
-        //
-        // If it is a GObject or MiniObject, read the g_class field to find
-        // the most exact class match
-        //
-        //  || MiniObject.class.isAssignableFrom(cls)
-        if (GObject.class.isAssignableFrom(cls)) {
+       
+
+        /* Special-case GObject.GObjectProxy here - these are interface values
+         * for which we don't know of a current concrete class.
+         */
+        if (GObject.GObjectProxy.class.isAssignableFrom(cls)) {
+        	cls = (Class<T>) getStubClassFor(cls);
+        /* For GObject, read the g_class field to find
+         * the most exact class match
+         */        	
+        } else if (GObject.class.isAssignableFrom(cls)) {
             cls = classFor(ptr, cls);
         }
+        /* Ok, something else, let's try to find an Initializer constructor
+         */
         try {
             Constructor<T> constructor = cls.getDeclaredConstructor(Initializer.class);
             constructor.setAccessible(true);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]