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



Author: walters
Date: Sat Sep  6 20:34:51 2008
New Revision: 38
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=38&view=rev

Log:
Handle both structures and unions; rework mapping


Added:
   trunk/src/org/gnome/gir/gobject/BoxedStructure.java
   trunk/src/org/gnome/gir/gobject/BoxedUnion.java
   trunk/src/org/gnome/gir/gobject/RegisteredType.java
Modified:
   trunk/src/org/gnome/gir/compiler/CodeFactory.java
   trunk/src/org/gnome/gir/gobject/GBoxed.java
   trunk/src/org/gnome/gir/gobject/GBoxedAPI.java
   trunk/src/org/gnome/gir/gobject/GObject.java
   trunk/src/org/gnome/gir/gobject/GType.java
   trunk/src/org/gnome/gir/gobject/GTypeMapper.java
   trunk/src/org/gnome/gir/repository/BaseInfo.java
   trunk/src/org/gnome/gir/repository/UnionInfo.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	Sat Sep  6 20:34:51 2008
@@ -1,6 +1,7 @@
 package org.gnome.gir.compiler;
 
 import static org.objectweb.asm.Opcodes.AASTORE;
+import static org.objectweb.asm.Opcodes.AALOAD;
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static org.objectweb.asm.Opcodes.ACC_ENUM;
 import static org.objectweb.asm.Opcodes.ACC_FINAL;
@@ -82,6 +83,7 @@
 import org.gnome.gir.repository.StructInfo;
 import org.gnome.gir.repository.TypeInfo;
 import org.gnome.gir.repository.TypeTag;
+import org.gnome.gir.repository.UnionInfo;
 import org.gnome.gir.repository.ValueInfo;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.FieldVisitor;
@@ -156,12 +158,18 @@
 		TypeInfo type = arg.getType();
 		if (type.getTag().equals(TypeTag.INTERFACE)) {
 			BaseInfo iface = arg.getType().getInterface();
-			/* Special case structure members; we need to use the
+			/* Special case structure/union members; we need to use the
 			 * $ByReference tag if the member is actually a pointer.
 			 */
-			if (iface instanceof StructInfo) {
-				StructInfo struct = (StructInfo) iface;
-				String internalName = getInternalNameMapped(struct);
+			if (iface instanceof StructInfo || iface instanceof UnionInfo) {
+				boolean hasFields;
+				if (iface instanceof StructInfo)
+					hasFields = ((StructInfo) iface).getFields().length > 0;
+				else
+					hasFields = ((UnionInfo) iface).getFields().length > 0;
+				if (!hasFields)
+					return Type.getType(Pointer.class);
+				String internalName = getInternalNameMapped(iface);
 				if (type.isPointer() && internalName.startsWith(GType.dynamicNamespace))
 					internalName += "$ByReference";
 				return Type.getObjectType(internalName);
@@ -512,6 +520,57 @@
 		mv.visitTypeInsn(CHECKCAST, compilation.internalName);
 		mv.visitInsn(ARETURN);
 		mv.visitMaxs(2, 1);
+		mv.visitEnd();
+		
+		/* For NativeMapped */
+		mv = compilation.writer.visitMethod(ACC_PUBLIC, "fromNative", "(Ljava/lang/Object;Lcom/sun/jna/FromNativeContext;)Ljava/lang/Object;", null, null);
+		mv.visitCode();
+		l0 = new Label();
+		mv.visitLabel(l0);
+		mv.visitVarInsn(ALOAD, 1);
+		mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
+		mv.visitVarInsn(ASTORE, 3);
+		l1 = new Label();
+		mv.visitLabel(l1);
+		mv.visitMethodInsn(INVOKESTATIC, compilation.internalName, "values", 
+				"()[L" + compilation.internalName +  ";");
+		mv.visitVarInsn(ALOAD, 3);
+		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
+		mv.visitInsn(AALOAD);
+		mv.visitInsn(ARETURN);
+		Label l2 = new Label();
+		mv.visitLabel(l2);
+		mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l2, 0);
+		mv.visitLocalVariable("nativeValue", "Ljava/lang/Object;", null, l0, l2, 1);
+		mv.visitLocalVariable("context", "Lcom/sun/jna/FromNativeContext;", null, l0, l2, 2);
+		mv.visitLocalVariable("val", "Ljava/lang/Integer;", null, l1, l2, 3);
+		mv.visitMaxs(2, 4);
+		mv.visitEnd();		
+		
+		mv = compilation.writer.visitMethod(ACC_PUBLIC, "nativeType", "()Ljava/lang/Class;", "()Ljava/lang/Class<*>;", null);
+		mv.visitCode();
+		l0 = new Label();
+		mv.visitLabel(l0);
+		mv.visitLdcInsn(Type.getType("Ljava/lang/Integer;"));
+		mv.visitInsn(ARETURN);
+		l1 = new Label();
+		mv.visitLabel(l1);
+		mv.visitLocalVariable("this", "Lorg/gnome/gir/compiler/TestEnum;", null, l0, l1, 0);
+		mv.visitMaxs(1, 1);
+		mv.visitEnd();
+		
+		mv = compilation.writer.visitMethod(ACC_PUBLIC, "toNative", "()Ljava/lang/Object;", null, null);
+		mv.visitCode();
+		l0 = new Label();
+		mv.visitLabel(l0);
+		mv.visitVarInsn(ALOAD, 0);
+		mv.visitMethodInsn(INVOKEVIRTUAL, compilation.internalName, "ordinal", "()I");
+		mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
+		mv.visitInsn(ARETURN);
+		l1 = new Label();
+		mv.visitLabel(l1);
+		mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l1, 0);
+		mv.visitMaxs(1, 1);
 		mv.visitEnd();		
 		
 		compilation.close();
@@ -1192,15 +1251,28 @@
 			return;	
 		writeCallable(ACC_PUBLIC + ACC_STATIC + ACC_FINAL, compilation, fi, ctx);
 	}
-	
-	private void compile(StructInfo info) {
-		MethodVisitor mv;
-		StubClassCompilation compilation = getCompilation(info);
+
+	private void writeStructUnion(RegisteredTypeInfo info, StubClassCompilation compilation, String type,
+			FunctionInfo[] methods,
+			FieldInfo[] fields) {
 		
 		String internalName = getInternalName(info);
-		compilation.writer.visit(V1_6, ACC_PUBLIC + ACC_SUPER, internalName, null, "com/sun/jna/Structure", null);	
+		String typeInit = info.getTypeInit();
+		boolean isRegistered = typeInit != null;
+		boolean hasFields = fields.length > 0;
+		if (hasFields) {
+			compilation.writer.visit(V1_6, ACC_PUBLIC + ACC_SUPER, internalName, null, 
+					(isRegistered ? "org/gnome/gir/gobject/Boxed" : "com/sun/jna/") + type, null);
+		} else {
+			compilation.writer.visit(V1_6, ACC_PUBLIC + ACC_SUPER, internalName, null, 
+					"com/sun/jna/Pointer", null);
+			return;
+		}
 		
-		InnerClassCompilation byRef = compilation.newInner("ByReference");				
+		if (isRegistered)
+			writeGetGType(info, compilation);
+		
+		InnerClassCompilation byRef = compilation.newInner("ByReference");
 		compilation.writer.visitInnerClass(compilation.internalName + "$ByReference",
 				compilation.internalName, "ByReference", ACC_PUBLIC + ACC_STATIC);
 		byRef.writer.visit(V1_6, ACC_PUBLIC + ACC_STATIC, 
@@ -1210,41 +1282,55 @@
 		compilation.writer.visitInnerClass(compilation.internalName + "$ByValue",
 				compilation.internalName, "ByValue", ACC_PUBLIC + ACC_STATIC);
 		byValue.writer.visit(V1_6, ACC_PUBLIC + ACC_STATIC, 
-				byValue.internalName, null, compilation.internalName, new String[] { "com/sun/jna/Structure$ByValue"});		
+				byValue.internalName, null, compilation.internalName, new String[] { "com/sun/jna/Structure$ByValue"});
 		
 		/* constructor */
-		mv = compilation.writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+		MethodVisitor mv = compilation.writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
 		mv.visitCode();
 		Label l0 = new Label();
 		mv.visitLabel(l0);
 		mv.visitVarInsn(ALOAD, 0);
-		mv.visitMethodInsn(INVOKESPECIAL, "com/sun/jna/Structure", "<init>", "()V");
+		mv.visitMethodInsn(INVOKESTATIC, "org/gnome/gir/gobject/GTypeMapper", "getInstance", "()Lorg/gnome/gir/gobject/GTypeMapper;");		
+		mv.visitMethodInsn(INVOKESPECIAL, "com/sun/jna/" + type, "<init>", "(Lcom/sun/jna/TypeMapper;)V");				
 		mv.visitInsn(RETURN);
 		Label l1 = new Label();
 		mv.visitLabel(l1);
 		mv.visitLocalVariable("this", "L" + compilation.internalName + ";", null, l0, l1, 0);
-		mv.visitMaxs(1, 1);
-		mv.visitEnd();		
+		mv.visitMaxs(2, 1);
+		mv.visitEnd();
 		
 		Set<String> sigs = new HashSet<String>();		
-		for (FunctionInfo fi : info.getMethods()) {
+		for (FunctionInfo fi : methods) {
 			CallableCompilationContext ctx = tryCompileCallable(fi, sigs);
 			if (ctx == null)
 				continue;			
 			writeCallable(ACC_PUBLIC, compilation, fi, ctx);	
 		}
-		
-		for (FieldInfo fi : info.getFields()) {
+		for (FieldInfo fi : fields) {
 			String name = ucaseToCamel(fi.getName());
-			Type type = toJava(fi);
-			if (type.equals(Type.VOID_TYPE)) // FIXME Temporary hack for GdkAtom
-				type = Type.getType(Pointer.class);
-			FieldVisitor fv = compilation.writer.visitField(ACC_PUBLIC, name, type.getDescriptor(), null, null);
+			Type fieldType = toJava(fi);
+			if (fieldType.equals(Type.VOID_TYPE)) // FIXME Temporary hack for GdkAtom
+				fieldType = Type.getType(Pointer.class);
+			FieldVisitor fv = compilation.writer.visitField(ACC_PUBLIC, name, fieldType.getDescriptor(), null, null);
 			fv.visitEnd();				
-		}
+		}		
+	}
+		
+	private void compile(StructInfo info) {
+		StubClassCompilation compilation = getCompilation(info);
+
+		writeStructUnion(info, compilation, "Structure", info.getMethods(), info.getFields());
 		
 		compilation.close();
-	}
+	}	
+	
+	private void compile(UnionInfo info) {
+		StubClassCompilation compilation = getCompilation(info);
+		
+		writeStructUnion(info, compilation, "Union", info.getMethods(), info.getFields());
+		
+		compilation.close();
+	}	
 	
 	private void compile(BoxedInfo info) {
 		ClassCompilation compilation = getCompilation(info);
@@ -1256,7 +1342,6 @@
 		mv.visitCode();
 		Label l0 = new Label();
 		mv.visitLabel(l0);
-		mv.visitLineNumber(6, l0);
 		mv.visitVarInsn(ALOAD, 0);
 		mv.visitMethodInsn(INVOKESPECIAL, "org/gnome/gir/gobject/GBoxed", "<init>", "()V");
 		mv.visitInsn(RETURN);
@@ -1344,6 +1429,8 @@
 				compileGlobal(getGlobals(namespace), (FunctionInfo) baseInfo, globalSigs);
 			} else if (baseInfo instanceof StructInfo) {
 				compile((StructInfo) baseInfo);
+			} else if (baseInfo instanceof UnionInfo) {
+				compile((UnionInfo) baseInfo);				
 			} else if (baseInfo instanceof BoxedInfo) {
 				compile((BoxedInfo) baseInfo);
 			} else if (baseInfo instanceof InterfaceInfo) {

Added: trunk/src/org/gnome/gir/gobject/BoxedStructure.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/BoxedStructure.java	Sat Sep  6 20:34:51 2008
@@ -0,0 +1,32 @@
+package org.gnome.gir.gobject;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+import com.sun.jna.TypeMapper;
+
+
+public abstract class BoxedStructure extends Structure implements RegisteredType {
+
+	private boolean isNative = false;
+	
+	protected BoxedStructure(TypeMapper mapper) {
+		super(mapper);
+	}	
+	
+	public BoxedStructure(Pointer pointer) {
+		Pointer retptr = GBoxedAPI.gboxed.g_boxed_copy(GType.of(this.getClass()), pointer);		
+		useMemory(retptr);
+		isNative = true;
+	}
+
+	protected void free() {
+		GBoxedAPI.gboxed.g_boxed_free(GType.of(this.getClass()), this.getPointer());
+	}
+	
+	@Override
+	public void finalize() throws Throwable {
+		if (isNative)
+			free();
+		super.finalize();
+	}
+}

Added: trunk/src/org/gnome/gir/gobject/BoxedUnion.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/BoxedUnion.java	Sat Sep  6 20:34:51 2008
@@ -0,0 +1,32 @@
+package org.gnome.gir.gobject;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.TypeMapper;
+import com.sun.jna.Union;
+
+
+public abstract class BoxedUnion extends Union implements RegisteredType {
+	
+	private boolean isNative = false;
+	
+	protected BoxedUnion(TypeMapper mapper) {
+		super(mapper);
+	}
+	
+	public BoxedUnion(Pointer pointer) {
+		Pointer retptr = GBoxedAPI.gboxed.g_boxed_copy(GType.of(this.getClass()), pointer);		
+		useMemory(retptr);
+		isNative = true;
+	}
+
+	protected void free() {
+		GBoxedAPI.gboxed.g_boxed_free(GType.of(this.getClass()), this.getPointer());
+	}
+	
+	@Override
+	public void finalize() throws Throwable {
+		if (isNative)
+			free();
+		super.finalize();
+	}
+}

Modified: trunk/src/org/gnome/gir/gobject/GBoxed.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GBoxed.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GBoxed.java	Sat Sep  6 20:34:51 2008
@@ -2,6 +2,5 @@
 
 import com.sun.jna.PointerType;
 
-public abstract class GBoxed extends PointerType {
-	public abstract GType getType();
+public abstract class GBoxed extends PointerType implements RegisteredType {
 }

Modified: trunk/src/org/gnome/gir/gobject/GBoxedAPI.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GBoxedAPI.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GBoxedAPI.java	Sat Sep  6 20:34:51 2008
@@ -48,6 +48,7 @@
 import java.util.HashMap;
 
 import com.sun.jna.Library;
+import com.sun.jna.Pointer;
 
 /**
  *
@@ -61,4 +62,6 @@
 	});
     
     GType g_closure_get_type();
+    Pointer g_boxed_copy(GType gtype, Pointer obj);
+    void g_boxed_free(GType gtype, Pointer obj);    
 }

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	Sat Sep  6 20:34:51 2008
@@ -149,10 +149,6 @@
     	this(getInitializer(gtype, args));
     }
     
-    GType getType(Class<?> klass) {
-    	return GType.OBJECT;
-    }
-    
     /**
      * Sets the value of a <tt>GObject</tt> property.
      *

Modified: trunk/src/org/gnome/gir/gobject/GType.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GType.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GType.java	Sat Sep  6 20:34:51 2008
@@ -45,6 +45,7 @@
 
 package org.gnome.gir.gobject;
 
+import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -186,7 +187,21 @@
     	Pointer g_class = ptr.getPointer(0);
     	NativeLong g_type = g_class.getNativeLong(0);
     	return lookupProxyClass(g_type);
-    };    
+    };
+    
+    /**
+     * Find the associated GType of a class.
+     * @param klass
+     * @return
+     */
+    public static final <T extends RegisteredType> GType of(Class<T> klass) {
+    	try {
+    		Method m = klass.getMethod("getGType", new Class<?>[] {});
+    		return (GType) m.invoke(null, new Object[] {});
+    	} catch (Exception e) {
+    		throw new RuntimeException(e);
+    	}
+    }
     
     public static final void init() {
     	GObjectAPI.gobj.g_type_init();

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	Sat Sep  6 20:34:51 2008
@@ -49,10 +49,10 @@
 import java.lang.reflect.Method;
 import java.net.URI;
 
-import org.gnome.gir.gobject.annotation.Return;
 import org.gnome.gir.gobject.annotation.ConstField;
 import org.gnome.gir.gobject.annotation.IncRef;
 import org.gnome.gir.gobject.annotation.Invalidate;
+import org.gnome.gir.gobject.annotation.Return;
 
 import com.sun.jna.CallbackParameterContext;
 import com.sun.jna.FromNativeContext;
@@ -158,6 +158,7 @@
             return Pointer.class;
         }
     };
+    
     private static TypeConverter enumConverter = new TypeConverter() {
 
         @SuppressWarnings(value = "unchecked")
@@ -177,7 +178,7 @@
             return EnumMapper.getInstance().intValue((Enum) arg);
         }
     };
-
+    
     private TypeConverter booleanConverter = new TypeConverter() {
         public Object toNative(Object arg, ToNativeContext context) {
             return Integer.valueOf(Boolean.TRUE.equals(arg) ? 1 : 0);

Added: trunk/src/org/gnome/gir/gobject/RegisteredType.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/RegisteredType.java	Sat Sep  6 20:34:51 2008
@@ -0,0 +1,5 @@
+package org.gnome.gir.gobject;
+
+public interface RegisteredType {
+	/* public GType getGType(); */
+}

Modified: trunk/src/org/gnome/gir/repository/BaseInfo.java
==============================================================================
--- trunk/src/org/gnome/gir/repository/BaseInfo.java	(original)
+++ trunk/src/org/gnome/gir/repository/BaseInfo.java	Sat Sep  6 20:34:51 2008
@@ -29,6 +29,8 @@
 			return new FunctionInfo(init);
 		if (itype == InfoType.STRUCT.ordinal())
 			return new StructInfo(init);
+		if (itype == InfoType.UNION.ordinal())
+			return new UnionInfo(init);		
 		if (itype == InfoType.BOXED.ordinal())
 			return new BoxedInfo(init);
 		if (itype == InfoType.INTERFACE.ordinal())

Modified: trunk/src/org/gnome/gir/repository/UnionInfo.java
==============================================================================
--- trunk/src/org/gnome/gir/repository/UnionInfo.java	(original)
+++ trunk/src/org/gnome/gir/repository/UnionInfo.java	Sat Sep  6 20:34:51 2008
@@ -1,7 +1,25 @@
 package org.gnome.gir.repository;
 
-import com.sun.jna.PointerType;
 
-public class UnionInfo extends PointerType {
+public class UnionInfo extends RegisteredTypeInfo {
 
+	protected UnionInfo(Initializer init) {
+		super(init);
+	}
+
+	public FieldInfo[] getFields() {
+		int n = GIntrospectionAPI.gi.g_union_info_get_n_fields(this);
+		FieldInfo[] ret = new FieldInfo[n];
+		for (int i = 0; i < n; i++)
+			ret[i] = GIntrospectionAPI.gi.g_union_info_get_field(this, i);
+		return ret;
+	}
+	
+	public FunctionInfo[] getMethods() {
+		int n = GIntrospectionAPI.gi.g_union_info_get_n_methods(this);
+		FunctionInfo[] ret = new FunctionInfo[n];
+		for (int i = 0; i < n; i++)
+			ret[i] = GIntrospectionAPI.gi.g_union_info_get_method(this, i);
+		return ret;
+	}	
 }



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