java-gobject-introspection r124 - in trunk: src/org/gnome/gir/compiler src/org/gnome/gir/gobject stub-examples
- From: walters svn gnome org
- To: svn-commits-list gnome org
- Subject: java-gobject-introspection r124 - in trunk: src/org/gnome/gir/compiler src/org/gnome/gir/gobject stub-examples
- Date: Sun, 16 Nov 2008 22:52:12 +0000 (UTC)
Author: walters
Date: Sun Nov 16 22:52:12 2008
New Revision: 124
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=124&view=rev
Log:
Rationalize memmgt; handle transfer-none objects and transfer-full strings
Modified:
trunk/src/org/gnome/gir/compiler/CodeFactory.java
trunk/src/org/gnome/gir/gobject/GObject.java
trunk/src/org/gnome/gir/gobject/GTypeMapper.java
trunk/src/org/gnome/gir/gobject/GlibRuntime.java
trunk/src/org/gnome/gir/gobject/Handle.java
trunk/src/org/gnome/gir/gobject/NativeObject.java
trunk/src/org/gnome/gir/gobject/RefCountedObject.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 Sun Nov 16 22:52:12 2008
@@ -69,10 +69,12 @@
import org.gnome.gir.gobject.GErrorException;
import org.gnome.gir.gobject.GErrorStruct;
+import org.gnome.gir.gobject.GObject;
import org.gnome.gir.gobject.GObjectAPI;
import org.gnome.gir.gobject.GType;
import org.gnome.gir.gobject.GlibAPI;
import org.gnome.gir.gobject.GlibRuntime;
+import org.gnome.gir.gobject.NativeObject;
import org.gnome.gir.gobject.annotation.Return;
import org.gnome.gir.repository.ArgInfo;
import org.gnome.gir.repository.BaseInfo;
@@ -1151,15 +1153,24 @@
String globalInternalsName = getInternals(fi);
String symbol = fi.getSymbol();
- Class<?> returnBox = TypeMap.getPrimitiveBox(ctx.returnType);
- Type returnTypeBox;
- if (returnBox != null)
- returnTypeBox = Type.getType(returnBox);
- else
- returnTypeBox = ctx.returnType;
-
Transfer returnTransfer = fi.getCallerOwns();
- if (returnBox == null) {
+ TypeInfo returnGIType = fi.getReturnType();
+ TypeTag returnTypeTag = returnGIType.getTag();
+ Class<?> primitiveBox = TypeMap.getPrimitiveBox(ctx.returnType);
+ Type nativeReturnType;
+ if (primitiveBox != null) {
+ nativeReturnType = Type.getType(primitiveBox);
+ } else if /* Now test for special return value transfer handling */
+ ((returnTransfer.equals(Transfer.NOTHING) &&
+ (returnTypeTag.equals(TypeTag.INTERFACE))) ||
+ (returnTransfer.equals(Transfer.EVERYTHING) &&
+ returnTypeTag.equals(TypeTag.UTF8))) {
+ nativeReturnType = Type.getType(Pointer.class);
+ } else {
+ nativeReturnType = ctx.returnType;
+ }
+
+ if (primitiveBox == null) {
AnnotationVisitor av = mv.visitAnnotation(Type.getDescriptor(Return.class), true);
av.visitEnum("transfer", Type.getDescriptor(Transfer.class), returnTransfer.name());
av.visitEnd();
@@ -1247,7 +1258,7 @@
if (ctx.returnType.equals(Type.VOID_TYPE)) {
mv.visitLdcInsn(Type.getType(Void.class));
} else {
- mv.visitLdcInsn(returnTypeBox);
+ mv.visitLdcInsn(nativeReturnType);
}
mv.visitVarInsn(ALOAD, argsOffset);
mv.visitFieldInsn(GETSTATIC, globalInternalsName, "invocationOptions", Type.getDescriptor(Map.class));
@@ -1258,10 +1269,28 @@
if (ctx.returnType.equals(Type.VOID_TYPE)) {
mv.visitInsn(POP);
} else {
- mv.visitTypeInsn(CHECKCAST, returnTypeBox.getInternalName());
- if (returnBox != null)
- mv.visitMethodInsn(INVOKEVIRTUAL, returnTypeBox.getInternalName(),
+ mv.visitTypeInsn(CHECKCAST, nativeReturnType.getInternalName());
+ if (primitiveBox != null) {
+ /* Turn primitive boxeds into the corresponding primitive */
+ mv.visitMethodInsn(INVOKEVIRTUAL, nativeReturnType.getInternalName(),
ctx.returnType.getClassName() + "Value", "()" + ctx.returnType.getDescriptor());
+ } else if (nativeReturnType != ctx.returnType) {
+ /* Special handling for return types; see above where nativeReturnType is calculated. */
+ if (returnTypeTag.equals(TypeTag.INTERFACE)) {
+ /* These are objects for which we do *not* own a reference. */
+ mv.visitLdcInsn(ctx.returnType);
+ mv.visitInsn(ICONST_0);
+ mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeObject.class), "objectFor",
+ Type.getMethodDescriptor(getType(NativeObject.class), new Type[] { getType(Pointer.class), getType(Class.class), Type.BOOLEAN_TYPE }));
+ mv.visitTypeInsn(CHECKCAST, ctx.returnType.getInternalName());
+ } else if (returnTypeTag.equals(TypeTag.UTF8)) {
+ /* 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 {
+ throw new IllegalArgumentException(String.format("Unhandled nativeReturn %s vs public %s", nativeReturnType, ctx.returnType));
+ }
+ }
}
if (ctx.throwsGError) {
jtarget = new Label();
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 Sun Nov 16 22:52:12 2008
@@ -51,6 +51,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.gnome.gir.gobject.GObjectAPI.GObjectStruct;
import org.gnome.gir.gobject.GObjectAPI.GParamSpec;
import org.gnome.gir.gobject.GObjectAPI.GToggleNotify;
import org.gnome.gir.gobject.GObjectAPI.GWeakNotify;
@@ -75,9 +76,19 @@
debugMemory = System.getProperty("jgir.debugMemory") != null;
}
- private static final void debugMemory(String fmt, Object... args) {
- if (debugMemory)
- System.err.println(String.format(fmt, (Object[])args));
+ private static final void debugMemory(GObject obj, String fmt, Object... args) {
+ if (debugMemory) {
+ Object[] newArgs = new Object[args.length+2];
+ System.arraycopy(args, 0, newArgs, 1, args.length);
+ newArgs[0] = obj;
+ if (obj != null) {
+ GObjectStruct objStruct = new GObjectAPI.GObjectStruct(obj);
+ newArgs[newArgs.length-1] = objStruct.ref_count;
+ } else {
+ newArgs[newArgs.length-1] = "<null>";
+ }
+ System.err.println(String.format(fmt, newArgs));
+ }
}
/* Hold a strong Java reference between this proxy object and any signal
@@ -107,7 +118,7 @@
* @param init
*/
public GObject(Initializer init) {
- super(init.needRef ? initializer(init.ptr, false, init.ownsHandle) : init);
+ super(init.ownsRef ? initializer(init.ptr, false, init.ownsHandle) : init);
if (init.ownsHandle) {
strongReferences.put(this, Boolean.TRUE);
@@ -116,10 +127,10 @@
*/
boolean wasFloating = GObjectAPI.gobj.g_object_is_floating(this);
if (wasFloating) {
- debugMemory("SINK AND TOGGLE %s", this);
+ debugMemory(this, "SINK AND TOGGLE %s %s");
GObjectAPI.gobj.g_object_ref_sink(this);
} else {
- debugMemory("TOGGLE %s", this);
+ debugMemory(this, "TOGGLE %s %s");
}
/* The toggle reference is our primary means of memory management between
@@ -132,10 +143,16 @@
*/
GObjectAPI.gobj.g_object_weak_ref(this, weakNotify, null);
- /* Since we normally have a strong reference given to us (except in special cases),
- * here we unref and this should normally just leave the toggle reference.
- */
- if (!init.needRef) {
+ /*
+ * Normally we have a strong reference given to us by constructors,
+ * GValue property gets, etc. So here we unref, leaving the toggle
+ * reference we just added.
+ *
+ * An example case where we don't own a ref are C convenience
+ * getters - need to ensure those are annotated with (transfer
+ * none).
+ */
+ if (init.ownsRef) {
unref();
}
}
@@ -229,22 +246,24 @@
}
@Override
protected void ref() {
- debugMemory("REF %s", this);
+ debugMemory(this, "REF %s %s");
GObjectAPI.gobj.g_object_ref(this);
}
@Override
protected void unref() {
- debugMemory("UNREF %s", this);
+ debugMemory(this, "UNREF %s %s");
GObjectAPI.gobj.g_object_unref(this);
}
+
+ @Override
protected void invalidate() {
try {
- debugMemory("INVALIDATE %s", this);
+ debugMemory(this, "INVALIDATE %s %s");
// Need to increase the ref count before removing the toggle ref, so
// ensure the native object is not destroyed.
if (ownsHandle.get()) {
- debugMemory("REMOVING TOGGLE %s", this);
+ debugMemory(this, "REMOVING TOGGLE %s %s");
ref();
// Disconnect the callback.
@@ -302,15 +321,6 @@
GSignalAPI.gsignal.g_signal_handler_disconnect(GObject.this, new NativeLong(id));
signalHandlers.remove(id);
}
-
- public static GObject objectFor(Pointer ptr, Class<? extends GObject> defaultClass) {
- return GObject.objectFor(ptr, defaultClass, true);
- }
-
- @SuppressWarnings("unchecked")
- public static <T extends GObject> T objectFor(Pointer ptr, Class<T> defaultClass, boolean needRef) {
- return NativeObject.objectFor(ptr, defaultClass, needRef);
- }
private GObjectAPI.GParamSpec findProperty(String propertyName) {
return GObjectAPI.gobj.g_object_class_find_property(handle().getPointer(0), propertyName);
@@ -343,7 +353,7 @@
@Override
public void callback(Pointer data, Pointer obj) {
GObject o = (GObject) NativeObject.instanceFor(obj);
- debugMemory("WEAK o=%s obj=%s", o, obj);
+ debugMemory(o, "WEAK %s %s obj=%s", o, obj);
// Clear out the signal handler references
if (o == null)
return;
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 Sun Nov 16 22:52:12 2008
@@ -102,29 +102,6 @@
return null;
}
Pointer ptr = ((NativeObject) arg).handle();
-
- //
- // Deal with any adjustments to the proxy neccessitated by gstreamer
- // breaking their reference-counting idiom with special cases
- //
- if (context instanceof MethodParameterContext) {
- MethodParameterContext mcontext = (MethodParameterContext) context;
- Method method = mcontext.getMethod();
- int index = mcontext.getParameterIndex();
- Annotation[][] parameterAnnotations = method.getParameterAnnotations();
- if (index < parameterAnnotations.length) {
- Annotation[] annotations = parameterAnnotations[index];
- for (int i = 0; i < annotations.length; ++i) {
- if (annotations[i] instanceof Invalidate) {
- ((Handle) arg).invalidate();
- break;
- } else if (annotations[i] instanceof IncRef) {
- ((RefCountedObject) arg).ref();
- break;
- }
- }
- }
- }
return ptr;
}
@@ -133,33 +110,15 @@
if (result == null) {
return null;
}
- if (context instanceof MethodResultContext) {
- //
- // By default, we assume objects have incremented reference counts.
- // Otherwise, the code generator should have created an @Return(transfer=NOTHING)
- // annotation.
- //
- Return anno = ((MethodResultContext) context).getMethod().getAnnotation(Return.class);
- boolean ownsHandle;
- if (anno == null || anno.transfer().equals(Transfer.EVERYTHING)) {
- ownsHandle = true;
- } else {
- ownsHandle = false;
- }
- int refadj = ownsHandle ? -1 : 0;
- return NativeObject.objectFor((Pointer) result, context.getTargetType(), refadj, ownsHandle);
- }
- if (context instanceof CallbackParameterContext) {
- return NativeObject.objectFor((Pointer) result, context.getTargetType(), 1, true);
- }
- if (context instanceof StructureReadContext) {
- StructureReadContext sctx = (StructureReadContext) context;
- boolean ownsHandle = sctx.getField().getAnnotation(ConstField.class) == null;
- return NativeObject.objectFor((Pointer) result, context.getTargetType(), 1, ownsHandle);
- }
if (context instanceof FunctionResultContext) {
- return NativeObject.objectFor((Pointer) result, context.getTargetType(), 0, true);
+ return NativeObject.objectFor((Pointer) result, context.getTargetType(), true, true);
+ }
+ if (context instanceof CallbackParameterContext || context instanceof StructureReadContext) {
+ return NativeObject.objectFor((Pointer) result, context.getTargetType(), false, true);
}
+ if (context instanceof MethodResultContext) {
+ throw new RuntimeException("Got illegal MethodResultContext in GTypeMapper");
+ }
throw new IllegalStateException("Cannot convert to NativeObject from " + context);
}
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 Sun Nov 16 22:52:12 2008
@@ -40,6 +40,12 @@
*/
private static final Set<CallbackData> outstandingCallbacks
= Collections.synchronizedSet(new HashSet<CallbackData>());
+
+ public static final String toStringAndGFree(Pointer ptr) {
+ String result = ptr.getString(0);
+ GlibAPI.glib.g_free(ptr);
+ return result;
+ }
public static final GlibAPI.GDestroyNotify createDestroyNotify(Callback callback) {
if (callback == null)
Modified: trunk/src/org/gnome/gir/gobject/Handle.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/Handle.java (original)
+++ trunk/src/org/gnome/gir/gobject/Handle.java Sun Nov 16 22:52:12 2008
@@ -51,25 +51,19 @@
// Use this to propagate low level pointer arguments up the constructor chain
protected static class Initializer {
public final Pointer ptr;
- public final boolean needRef, ownsHandle;
- public Initializer() {
- this.ptr = null;
- this.needRef = false;
- this.ownsHandle = false;
- }
+ public final boolean ownsRef, ownsHandle;
+
public Initializer(Pointer ptr) {
- this(ptr, false, true);
+ this(ptr, true, true);
}
- public Initializer(Pointer ptr, boolean needRef, boolean ownsHandle) {
+ public Initializer(Pointer ptr, boolean ownsRef, boolean ownsHandle) {
if (ptr == null)
throw new RuntimeException("Invalid NULL pointer for initializer");
this.ptr = ptr;
- this.needRef = needRef;
+ this.ownsRef = ownsRef;
this.ownsHandle = ownsHandle;
}
- }
-
- protected static final Initializer defaultInit = new Initializer();
+ }
public Handle() {
}
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 Sun Nov 16 22:52:12 2008
@@ -162,11 +162,8 @@
}
return ref != null ? ref.get() : null;
}
- public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean needRef) {
- return objectFor(ptr, cls, needRef, true);
- }
- public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean needRef, boolean ownsHandle) {
- return objectFor(ptr, cls, needRef ? 1 : 0, ownsHandle);
+ public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef) {
+ return objectFor(ptr, cls, ownsRef, true);
}
private static Class<?> getStubClassFor(Class<?> proxyClass) {
@@ -179,7 +176,7 @@
}
@SuppressWarnings("unchecked")
- public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, int refAdjust, boolean ownsHandle) {
+ public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef, boolean ownsHandle) {
// Ignore null pointers
if (ptr == null) {
return null;
@@ -190,7 +187,7 @@
else if (GObject.class.isAssignableFrom(cls) || GObject.GObjectProxy.class.isAssignableFrom(cls))
obj = NativeObject.instanceFor(ptr);
if (obj != null && cls.isInstance(obj)) {
- if (refAdjust < 0) {
+ if (ownsRef) {
((RefCountedObject) obj).unref(); // Lose the extra ref that we expect functions to add by default
}
return cls.cast(obj);
@@ -217,7 +214,7 @@
try {
Constructor<T> constructor = cls.getDeclaredConstructor(Initializer.class);
constructor.setAccessible(true);
- T retVal = constructor.newInstance(initializer(ptr, refAdjust > 0, ownsHandle));
+ T retVal = constructor.newInstance(initializer(ptr, ownsRef, ownsHandle));
//retVal.initNativeHandle(ptr, refAdjust > 0, ownsHandle);
return retVal;
} catch (SecurityException ex) {
Modified: trunk/src/org/gnome/gir/gobject/RefCountedObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/RefCountedObject.java (original)
+++ trunk/src/org/gnome/gir/gobject/RefCountedObject.java Sun Nov 16 22:52:12 2008
@@ -53,7 +53,7 @@
/** Creates a new instance of RefCountedObject */
protected RefCountedObject(Initializer init) {
super(init);
- if (init.ownsHandle && init.needRef) {
+ if (init.ownsHandle && init.ownsRef) {
ref();
}
}
Modified: trunk/stub-examples/Test.java
==============================================================================
--- trunk/stub-examples/Test.java (original)
+++ trunk/stub-examples/Test.java Sun Nov 16 22:52:12 2008
@@ -8,6 +8,7 @@
import org.gnome.gir.gobject.GObject;
import org.gnome.gir.gobject.GType;
import org.gnome.gir.gobject.GTypeMapper;
+import org.gnome.gir.gobject.NativeObject;
import org.gnome.gir.gobject.annotation.Return;
import org.gnome.gir.repository.Direction;
import org.gnome.gir.repository.Repository;
@@ -79,7 +80,7 @@
if (error.getValue() != null) {
throw new GErrorException(new GErrorStruct(error.getValue()));
}
- return (Test) objectFor(result, Test.class);
+ return (Test) NativeObject.objectFor(result, Test.class, false);
}
public static Test newWithFoo(String blah) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]