java-gobject-introspection r139 - in trunk: src/org/gnome/gir/compiler src/org/gnome/gir/gobject stub-examples



Author: walters
Date: Sat Nov 29 19:15:30 2008
New Revision: 139
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=139&view=rev

Log:
Add support for GList/GSList conversion to java.util.List, with generics

Added:
   trunk/src/org/gnome/gir/gobject/GenericGList.java
Modified:
   trunk/src/org/gnome/gir/compiler/CodeFactory.java
   trunk/src/org/gnome/gir/compiler/TypeMap.java
   trunk/src/org/gnome/gir/gobject/GList.java
   trunk/src/org/gnome/gir/gobject/GSList.java
   trunk/src/org/gnome/gir/gobject/GType.java
   trunk/src/org/gnome/gir/gobject/GlibRuntime.java
   trunk/stub-examples/Test.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 Nov 29 19:15:30 2008
@@ -69,8 +69,11 @@
 
 import org.gnome.gir.gobject.GErrorException;
 import org.gnome.gir.gobject.GErrorStruct;
+import org.gnome.gir.gobject.GList;
 import org.gnome.gir.gobject.GObjectAPI;
+import org.gnome.gir.gobject.GSList;
 import org.gnome.gir.gobject.GType;
+import org.gnome.gir.gobject.GenericGList;
 import org.gnome.gir.gobject.GlibAPI;
 import org.gnome.gir.gobject.GlibRuntime;
 import org.gnome.gir.gobject.NativeObject;
@@ -106,6 +109,8 @@
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureVisitor;
+import org.objectweb.asm.signature.SignatureWriter;
 import org.objectweb.asm.util.CheckClassAdapter;
 
 import com.sun.jna.Callback;
@@ -183,6 +188,37 @@
 	static String getInternalNameMapped(BaseInfo info) {
 		return GType.getInternalNameMapped(info.getNamespace(), info.getName());
 	}	
+	
+	static boolean writeConversionToJava(MethodVisitor mv, TypeInfo info, Transfer transfer) {
+		TypeTag infoTag = info.getTag();
+		if (infoTag.equals(TypeTag.GLIST) || infoTag.equals(TypeTag.GSLIST)) {
+			if (infoTag.equals(TypeTag.GLIST)) {			
+				mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GList.class), "fromNative",
+						Type.getMethodDescriptor(getType(GList.class), new Type[] { getType(Pointer.class) }));
+			} else {
+				mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GSList.class), "fromNative",
+						Type.getMethodDescriptor(getType(GSList.class), new Type[] { getType(Pointer.class) }));				
+			}
+			mv.visitFieldInsn(GETSTATIC, getType(Transfer.class).getInternalName(), 
+					transfer.name(), getType(Transfer.class).getDescriptor());
+			TypeInfo param = info.getParamType(0);
+			TypeTag paramTag = param.getTag();
+			if (paramTag.equals(TypeTag.UTF8)) {
+				mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GlibRuntime.class), "convertListUtf8",
+						Type.getMethodDescriptor(getType(List.class), new Type[] { getType(GenericGList.class), getType(Transfer.class) }));
+				return true;
+			} else if (paramTag.equals(TypeTag.INTERFACE)) {
+				BaseInfo paramInfo = param.getInterface();
+				Type eltClass = TypeMap.typeFromInfo(paramInfo);
+				mv.visitLdcInsn(eltClass);
+				mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GlibRuntime.class), "convertListGObject",
+						Type.getMethodDescriptor(getType(List.class), new Type[] { getType(GenericGList.class), getType(Transfer.class), getType(Class.class) }));				
+				return true;
+			}
+		}
+
+		return false;		
+	}
 
 	private void compile(EnumInfo info) {
 		ClassCompilation compilation = getCompilation(info);
@@ -970,6 +1006,7 @@
 		ArgInfo[] args;
 		Type thisType;
 		List<Type> argTypes;
+		String argSignature;
 		List<String> argNames = new ArrayList<String>();
 		boolean throwsGError;
 		boolean isInterfaceMethod = false;
@@ -1053,7 +1090,16 @@
 		} else {
 			if (ctx.isMethod && thisType != null)
 				ctx.thisType = Type.getObjectType(getInternalNameMapped(thisType));
-			ctx.returnType = TypeMap.getCallableReturn(si);
+			ctx.returnType = TypeMap.getCallableReturn(si);		
+			if (ctx.returnType != null && TypeMap.visitCallableReturnSignature(si, null)) {
+				SignatureVisitor visitor = new SignatureWriter();
+				SignatureVisitor returnVisitor = visitor.visitReturnType();
+				returnVisitor.visitClassType(ctx.returnType.getInternalName());
+				if (TypeMap.visitCallableReturnSignature(si, returnVisitor)) {
+					visitor.visitEnd();
+					ctx.argSignature = visitor.toString();
+				}
+			}
 		}
 		if (ctx.returnType == null) {
 			logger.warning("Skipping callable with unhandled return signature: "+ si.getIdentifier());
@@ -1150,9 +1196,9 @@
 		
 		if (fi.isDeprecated()) {
 			accessFlags += ACC_DEPRECATED;
-		}		
+		}
 		MethodVisitor mv = compilation.writer.visitMethod(accessFlags, 
-				name, descriptor, null, exceptions);
+				name, descriptor, ctx.argSignature, exceptions);
 		if (fi.isDeprecated()) {
 			AnnotationVisitor av = mv.visitAnnotation(Type.getType(Deprecated.class).getDescriptor(), true);
 			av.visitEnd();
@@ -1172,7 +1218,9 @@
 			((returnTransfer.equals(Transfer.NOTHING) &&
 				 (returnTypeTag.equals(TypeTag.INTERFACE))) ||
 				(returnTransfer.equals(Transfer.EVERYTHING) && 
-				 returnTypeTag.equals(TypeTag.UTF8))) {
+				 returnTypeTag.equals(TypeTag.UTF8)) || 
+			 returnTypeTag.equals(TypeTag.GLIST) ||
+			 returnTypeTag.equals(TypeTag.GSLIST)) {
 			nativeReturnType = Type.getType(Pointer.class);
 		} else { 
 			nativeReturnType = ctx.returnType;
@@ -1295,6 +1343,8 @@
 					/* Strings which are *not* const and must be g_free'd */
 					mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GlibRuntime.class), "toStringAndGFree", 
 							Type.getMethodDescriptor(getType(String.class), new Type[] { getType(Pointer.class) }));
+				} else if (returnTypeTag.equals(TypeTag.GLIST) || returnTypeTag.equals(TypeTag.GSLIST)) {
+					writeConversionToJava(mv, returnGIType, returnTransfer);
 				} else {
 					throw new IllegalArgumentException(String.format("Unhandled nativeReturn %s vs public %s", nativeReturnType, ctx.returnType));
 				}

Modified: trunk/src/org/gnome/gir/compiler/TypeMap.java
==============================================================================
--- trunk/src/org/gnome/gir/compiler/TypeMap.java	(original)
+++ trunk/src/org/gnome/gir/compiler/TypeMap.java	Sat Nov 29 19:15:30 2008
@@ -26,6 +26,7 @@
 import org.gnome.gir.repository.TypeTag;
 import org.gnome.gir.repository.UnionInfo;
 import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureVisitor;
 
 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
@@ -135,11 +136,51 @@
 
 	static Type getCallableReturn(CallableInfo callable) {
 		TypeInfo info = callable.getReturnType();
-		if (info.getTag().equals(TypeTag.INTERFACE)) {
+		TypeTag tag = info.getTag();
+		if (tag.equals(TypeTag.INTERFACE)) {
 			return TypeMap.typeFromInfo(info);
+		} else if (tag.equals(TypeTag.GLIST) || tag.equals(TypeTag.GSLIST)) {
+			if (!isCallableReturnSignatureSupported(callable))
+				return null;
+			return Type.getType(List.class);
 		}
 		return toJava(info.getTag());
 	}
+	
+	private static boolean isCallableReturnSignatureSupported(CallableInfo callable) {
+		TypeInfo info = callable.getReturnType();
+		TypeTag tag = info.getTag();		
+		if (!(tag.equals(TypeTag.GLIST) || tag.equals(TypeTag.GSLIST)))
+			return true;
+		TypeInfo param = info.getParamType(0);
+		TypeTag paramTag = param.getTag();
+		if (!(paramTag.equals(TypeTag.UTF8) || paramTag.equals(TypeTag.INTERFACE)))
+			return false;
+		if (paramTag.equals(TypeTag.INTERFACE)) {
+			BaseInfo paramInfo = param.getInterface();
+			if (!(paramInfo instanceof ObjectInfo || paramInfo instanceof InterfaceInfo))
+				return false;
+		}
+		Type containedType = toJava(param);
+		if (containedType == null)
+			return false;
+		return true;
+	}
+	
+	public static boolean visitCallableReturnSignature(CallableInfo callable, SignatureVisitor visitor) {
+		TypeInfo info = callable.getReturnType();
+		TypeTag tag = info.getTag();
+		if (!(tag.equals(TypeTag.GLIST) || tag.equals(TypeTag.GSLIST)))
+			return false;
+		TypeInfo param = info.getParamType(0);
+		Type containedType = toJava(param);
+		if (visitor == null)
+			return true;
+		SignatureVisitor paramVisitor = visitor.visitTypeArgument('=');
+		paramVisitor.visitClassType(containedType.getInternalName());
+		paramVisitor.visitEnd();
+		return true;
+	}
 
 	public static Type toJava(ArgInfo arg) {
 		if (arg.getDirection() == Direction.IN) {

Modified: trunk/src/org/gnome/gir/gobject/GList.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GList.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GList.java	Sat Nov 29 19:15:30 2008
@@ -3,27 +3,51 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.gnome.gir.repository.Transfer;
+
 import com.sun.jna.Pointer;
 import com.sun.jna.Structure;
 
-public class GList extends Structure {
-	public static class ByReference extends GList implements Structure.ByReference {};
+public class GList extends Structure implements GenericGList {
+	public static class ByReference extends GList implements Structure.ByReference {
+		public ByReference() {
+			super();
+		}
+		protected ByReference(Pointer p) {
+			super(p);
+		}
+	};
 	
 	public Pointer data;
 	public GList.ByReference next;
 	public GList.ByReference prev;	
 	
-	public List<Pointer> copy() {
-		List<Pointer> ret = new ArrayList<Pointer>();
-		GList list = this;
-		while (list.next != null) {
-			ret.add(list.data);
-			list = list.next;
-		}
-		return ret;
+	protected GList(Pointer p) {
+		useMemory(p);
+		read();
 	}
-	
+
+	public GList() {
+	}
+
+	public static GList fromNative(Pointer p) {
+		if (p == null)
+			return null;
+		return new GList(p);
+	}
+
+	@Override
 	public void free() {
 		GlibAPI.glib.g_list_free(this);
 	}
+
+	@Override
+	public Pointer getData() {
+		return data;
+	}
+
+	@Override
+	public GenericGList getNext() {
+		return next;
+	}
 }

Modified: trunk/src/org/gnome/gir/gobject/GSList.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GSList.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GSList.java	Sat Nov 29 19:15:30 2008
@@ -1,28 +1,48 @@
 package org.gnome.gir.gobject;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import com.sun.jna.Pointer;
 import com.sun.jna.Structure;
 
-public class GSList extends Structure {
-	public static class ByReference extends GSList implements Structure.ByReference {};
+public class GSList extends Structure implements GenericGList {
+	public static class ByReference extends GSList implements Structure.ByReference {
+		public ByReference() {
+			super();
+		}
+		protected ByReference(Pointer p) {
+			super(p);
+		}		
+	};
 	
 	public Pointer data;
 	public GSList.ByReference next;
 	
-	public List<Pointer> copy() {
-		List<Pointer> ret = new ArrayList<Pointer>();
-		GSList list = this;
-		while (list.next != null) {
-			ret.add(list.data);
-			list = list.next;
-		}
-		return ret;
+	protected GSList(Pointer p) {
+		useMemory(p);
+		read();
 	}
+
+	public GSList() {
+		super();
+	}
+
+	public static GSList fromNative(Pointer p) {
+		if (p == null)
+			return null;
+		return new GSList(p);
+	}	
 	
+	@Override
 	public void free() {
 		GlibAPI.glib.g_slist_free(this);
-	}	
+	}
+
+	@Override
+	public Pointer getData() {
+		return data;
+	}
+
+	@Override
+	public GenericGList getNext() {
+		return next;
+	}
 }

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 Nov 29 19:15:30 2008
@@ -70,8 +70,6 @@
 
 		{
 			put("GLib.Value", "org/gnome/gir/gobject/GValue");
-			put("GLib.List", "org/gnome/gir/gobject/GList");
-			put("GLib.SList", "org/gnome/gir/gobject/GSList");
 
 			put("GLib.MainContext", "org/gnome/gir/gobject/GMainContext");
 			put("GLib.Closure", "org/gnome/gir/gobject/GClosure");
@@ -94,7 +92,7 @@
 					"MappedFile" };
 			for (String unmapped : glibPointerUnmapped)
 				put("GLib." + unmapped, "com/sun/jna/Pointer");
-			String[] glibIntegerUnmapped = new String[] { "SpawnFlags", "SeekType", "IOCondition", "RegexMatchFlags" };
+			String[] glibIntegerUnmapped = new String[] { "GList", "GSList", "SpawnFlags", "SeekType", "IOCondition", "RegexMatchFlags" };
 			for (String unmapped : glibIntegerUnmapped)
 				put("GLib." + unmapped, "java/lang/Integer");			
 			

Added: trunk/src/org/gnome/gir/gobject/GenericGList.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/GenericGList.java	Sat Nov 29 19:15:30 2008
@@ -0,0 +1,9 @@
+package org.gnome.gir.gobject;
+
+import com.sun.jna.Pointer;
+
+public interface GenericGList {
+	public abstract Pointer getData();
+	public abstract GenericGList getNext();
+	public abstract void free();		
+}

Modified: trunk/src/org/gnome/gir/gobject/GlibRuntime.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GlibRuntime.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GlibRuntime.java	Sat Nov 29 19:15:30 2008
@@ -22,10 +22,14 @@
 
 package org.gnome.gir.gobject;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
+import org.gnome.gir.repository.Transfer;
+
 import com.sun.jna.Callback;
 import com.sun.jna.Pointer;
 
@@ -63,4 +67,35 @@
 		outstandingCallbacks.add(data);
 		return destroy;
 	}
+	
+	public static List<String> convertListUtf8(GenericGList glist, Transfer transfer) {
+		List<String> ret = new ArrayList<String>();
+		GenericGList origList = glist;
+		boolean stringFree = transfer.equals(Transfer.EVERYTHING);
+		while (glist != null) {
+			Pointer data = glist.getData();
+			String p = data.getString(0);
+			if (stringFree)
+				GlibAPI.glib.g_free(data);
+			ret.add(p);
+			glist = glist.getNext();
+		}
+		if (!transfer.equals(Transfer.NOTHING))
+			origList.free();
+		return ret;
+	}
+	
+	public static List<GObject> convertListGObject(GenericGList glist, Transfer transfer, Class<? extends NativeObject> klass) {
+		List<GObject> ret = new ArrayList<GObject>();
+		GenericGList origList = glist;		
+		boolean objTransfer = transfer.equals(Transfer.EVERYTHING);
+		while (glist != null) {
+			GObject obj = (GObject) NativeObject.Internals.objectFor(glist.getData(), klass, objTransfer);
+			ret.add(obj);
+			glist = glist.getNext();
+		}
+		if (!transfer.equals(Transfer.NOTHING))
+			origList.free();		
+		return ret;
+	}		
 }

Modified: trunk/stub-examples/Test.java
==============================================================================
--- trunk/stub-examples/Test.java	(original)
+++ trunk/stub-examples/Test.java	Sat Nov 29 19:15:30 2008
@@ -1,13 +1,17 @@
 
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.gnome.gir.gobject.GErrorException;
 import org.gnome.gir.gobject.GErrorStruct;
+import org.gnome.gir.gobject.GList;
 import org.gnome.gir.gobject.GObject;
 import org.gnome.gir.gobject.GType;
 import org.gnome.gir.gobject.GTypeMapper;
+import org.gnome.gir.gobject.GlibRuntime;
 import org.gnome.gir.gobject.NativeObject;
 import org.gnome.gir.gobject.annotation.Return;
 import org.gnome.gir.repository.Direction;
@@ -180,6 +184,14 @@
 		f.invoke(Void.class, args, Internals.invocationOptions);		
 	}
 	
+	public List<GObject> cow() {
+		Function f = Internals.library.getFunction("gtk_cow");
+		Object[] args = new Object[] { this };
+		Pointer p = (Pointer) f.invoke(Pointer.class, args, Internals.invocationOptions);
+		GList list = GList.fromNative(p);
+		return GlibRuntime.convertListGObject(list, Transfer.EVERYTHING, GObject.class);
+	}
+	
 	public void ifaceFoo(String blah) {
 		Function f = Internals.library.getFunction("gtk_propagate_event");
 		Object[] args = new Object[] { this, blah };



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