java-gobject-introspection r105 - 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 r105 - in trunk: src/org/gnome/gir/compiler src/org/gnome/gir/gobject stub-examples
- Date: Thu, 23 Oct 2008 03:15:12 +0000 (UTC)
Author: walters
Date: Thu Oct 23 03:15:12 2008
New Revision: 105
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=105&view=rev
Log:
Generate DestroyNotify handlers for functions which take them
Added:
trunk/src/org/gnome/gir/gobject/GSourceFunc.java
trunk/src/org/gnome/gir/gobject/GlibRuntime.java
Modified:
trunk/src/org/gnome/gir/compiler/CodeFactory.java
trunk/src/org/gnome/gir/gobject/GObject.java
trunk/src/org/gnome/gir/gobject/GSource.java
trunk/src/org/gnome/gir/gobject/GType.java
trunk/src/org/gnome/gir/gobject/GlibAPI.java
trunk/src/org/gnome/gir/gobject/MainLoop.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 Thu Oct 23 03:15:12 2008
@@ -78,6 +78,8 @@
import org.gnome.gir.gobject.GObjectAPI;
import org.gnome.gir.gobject.GSList;
import org.gnome.gir.gobject.GType;
+import org.gnome.gir.gobject.GlibAPI;
+import org.gnome.gir.gobject.GlibRuntime;
import org.gnome.gir.gobject.UnmappedPointer;
import org.gnome.gir.gobject.annotation.Return;
import org.gnome.gir.repository.ArgInfo;
@@ -115,6 +117,7 @@
import org.objectweb.asm.Type;
import org.objectweb.asm.util.CheckClassAdapter;
+import com.sun.jna.Callback;
import com.sun.jna.Function;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
@@ -1392,7 +1395,7 @@
Map<Integer, Integer> lengthOfArrayIndices = new HashMap<Integer,Integer>();
Map<Integer, Integer> arrayToLengthIndices = new HashMap<Integer,Integer>();
Set<Integer> userDataIndices = new HashSet<Integer>();
- Set<Integer> destroyNotifyIndices = new HashSet<Integer>();
+ Map<Integer,Integer> destroyNotifyIndices = new HashMap<Integer,Integer>();
public CallableCompilationContext() {
// TODO Auto-generated constructor stub
@@ -1410,7 +1413,7 @@
Set<Integer> eliminated = new HashSet<Integer>();
eliminated.addAll(lengthOfArrayIndices.keySet());
eliminated.addAll(userDataIndices);
- eliminated.addAll(destroyNotifyIndices);
+ eliminated.addAll(destroyNotifyIndices.keySet());
return eliminated;
}
@@ -1473,6 +1476,7 @@
ArgInfo[] args = ctx.args;
List<Type> types = new ArrayList<Type>();
+ int firstSeenCallback = -1;
for (int i = 0; i < args.length; i++) {
ArgInfo arg = args[i];
Type t;
@@ -1484,34 +1488,38 @@
logger.warning("Skipping callable with invalid error argument: " + si.getIdentifier());
return null;
}
+ int argOffset = i;
+ if (ctx.isMethod) argOffset++;
if (tag.equals(TypeTag.VOID) && arg.getName().contains("data")) {
- int dataIdx = i;
- if (ctx.isMethod) dataIdx++;
- ctx.userDataIndices.add(dataIdx);
+ ctx.userDataIndices.add(argOffset);
continue;
} else if (isDestroyNotify(arg)) {
- int dataIdx = i;
- if (ctx.isMethod) dataIdx++;
- ctx.destroyNotifyIndices.add(dataIdx);
+ if (firstSeenCallback == -1) {
+ logger.warning("Skipping callable with unpaired DestroyNotify: " + si.getIdentifier());
+ return null;
+ }
+ ctx.destroyNotifyIndices.put(argOffset, firstSeenCallback);
continue;
- }
+ } else if (arg.getDirection() == Direction.IN &&
+ info.getTag().equals(TypeTag.INTERFACE) &&
+ info.getInterface() instanceof CallbackInfo) {
+ if (firstSeenCallback >= 0) {
+ logger.warning("Skipping callable with unpaired multiple callbacks: " + si.getIdentifier());
+ return null;
+ }
+ firstSeenCallback = argOffset;
+ } else if (tag.equals(TypeTag.ARRAY) && arg.getDirection().equals(Direction.IN)) {
+ int lenIdx = arg.getType().getArrayLength();
+ if (lenIdx >= 0) {
+ ctx.lengthOfArrayIndices.put(lenIdx, argOffset);
+ ctx.arrayToLengthIndices.put(argOffset, lenIdx);
+ }
+ }
t = toJava(arg);
if (t == null) {
logger.warning(String.format("Unhandled argument %s in callable %s", arg, si.getIdentifier()));
return null;
}
- if (tag.equals(TypeTag.ARRAY) && arg.getDirection().equals(Direction.IN)) {
- int lenIdx = arg.getType().getArrayLength();
- if (lenIdx >= 0) {
- /* FIXME - remove this hack when the repository is fixed */
- int arrIdx = i;
- if (ctx.isMethod) {
- arrIdx++;
- }
- ctx.lengthOfArrayIndices.put(lenIdx, arrIdx);
- ctx.arrayToLengthIndices.put(arrIdx, lenIdx);
- }
- }
types.add(t);
ctx.argNames.add(arg.getName());
}
@@ -1723,6 +1731,7 @@
mv.visitIntInsn(BIPUSH, i);
Integer arraySource = ctx.lengthOfArrayIndices.get(i);
Integer lengthOfArray = ctx.arrayToLengthIndices.get(i);
+ Integer callbackIdx = ctx.destroyNotifyIndices.get(i);
if (arraySource != null) {
ArgInfo source = ctx.args[arraySource - (ctx.isMethod ? 1 : 0)];
assert source.getType().getTag().equals(TypeTag.ARRAY);
@@ -1735,12 +1744,15 @@
} else if (lengthOfArray != null) {
LocalVariable var = locals.get(lengthOfArray);
writeLoadArgument(mv, var.offset, var.type);
- } else if (ctx.userDataIndices.contains(i) || ctx.destroyNotifyIndices.contains(i)) {
+ } else if (ctx.userDataIndices.contains(i)) {
/* Always pass null for user datas - Java allows environment capture */
- /* For destroy notifies, we always pass null too; in the future we may want
- * to clean up any allocated callback data here?
- */
mv.visitInsn(ACONST_NULL);
+ } else if (callbackIdx != null) {
+ int offset = ctx.argOffsetToApi(callbackIdx);
+ LocalVariable var = locals.get(offset);
+ writeLoadArgument(mv, var.offset, var.type);
+ mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(GlibRuntime.class), "createDestroyNotify",
+ Type.getMethodDescriptor(getType(GlibAPI.GDestroyNotify.class), new Type[] { getType(Callback.class) } ));
} else if (!ctx.isMethod || i > 0) {
int localOff = ctx.argOffsetToApi(i);
LocalVariable var = locals.get(localOff);
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 Thu Oct 23 03:15:12 2008
@@ -71,7 +71,7 @@
private static final boolean debugMemory = false;
- private static final void debugMemory(String fmt, String... args) {
+ private static final void debugMemory(String fmt, Object... args) {
if (debugMemory)
System.err.println(String.format(fmt, (Object[])args));
}
@@ -105,7 +105,6 @@
public GObject(Initializer init) {
super(init.needRef ? initializer(init.ptr, false, init.ownsHandle) : init);
if (init.ownsHandle) {
- debugMemory("INIT OWNERSHIP " + this);
strongReferences.put(this, Boolean.TRUE);
/* Floating refs are just a convenience for C; we always want only strong
@@ -113,7 +112,6 @@
*/
boolean wasFloating = GObjectAPI.gobj.g_object_is_floating(this);
if (wasFloating) {
- debugMemory("Sinking " + this);
GObjectAPI.gobj.g_object_ref_sink(this);
}
@@ -224,22 +222,22 @@
}
@Override
protected void ref() {
- debugMemory("REF " + this);
+ debugMemory("REF %s", this);
GObjectAPI.gobj.g_object_ref(this);
}
@Override
protected void unref() {
- debugMemory("UNREF " + this);
+ debugMemory("UNREF %s", this);
GObjectAPI.gobj.g_object_unref(this);
}
protected void invalidate() {
try {
- debugMemory("INVALIDATE " + this);
+ debugMemory("INVALIDATE %s", this);
// 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 " + this);
+ debugMemory("REMOVING TOGGLE %s", this);
ref();
// Disconnect the callback.
@@ -323,7 +321,6 @@
* be retained for later retrieval
*/
GObject o = (GObject) NativeObject.instanceFor(ptr);
- debugMemory(String.format("TOGGLE o=%s is_last=%s", o, is_last_ref));
if (o == null) {
return;
}
@@ -339,7 +336,7 @@
@Override
public void callback(Pointer data, Pointer obj) {
GObject o = (GObject) NativeObject.instanceFor(obj);
- debugMemory(String.format("WEAK o=%s obj=%s", o, obj));
+ debugMemory("WEAK o=%s obj=%s", o, obj);
// Clear out the signal handler references
if (o == null)
return;
Modified: trunk/src/org/gnome/gir/gobject/GSource.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GSource.java (original)
+++ trunk/src/org/gnome/gir/gobject/GSource.java Thu Oct 23 03:15:12 2008
@@ -61,7 +61,7 @@
return GlibAPI.glib.g_source_attach(this, context);
}
public void setCallback(final Callable<Boolean> call) {
- this.callback = new GlibAPI.GSourceFunc() {
+ this.callback = new GSourceFunc() {
public boolean callback(Pointer data) {
if (GlibAPI.glib.g_source_is_destroyed(handle())) {
return false;
@@ -75,7 +75,7 @@
};
GlibAPI.glib.g_source_set_callback(this, callback, null, null);
}
- private GlibAPI.GSourceFunc callback;
+ private GSourceFunc callback;
protected void ref() {
GlibAPI.glib.g_source_ref(handle());
Added: trunk/src/org/gnome/gir/gobject/GSourceFunc.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/GSourceFunc.java Thu Oct 23 03:15:12 2008
@@ -0,0 +1,11 @@
+/**
+ *
+ */
+package org.gnome.gir.gobject;
+
+import com.sun.jna.Callback;
+import com.sun.jna.Pointer;
+
+public interface GSourceFunc extends Callback {
+ boolean callback(Pointer data);
+}
\ No newline at end of file
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 Thu Oct 23 03:15:12 2008
@@ -86,9 +86,10 @@
put("GLib.Mutex", "org/gnome/gir/gobject/GlibAPI$GMutex");
put("GLib.StaticRecMutex", "org/gnome/gir/gobject/GlibAPI$GStaticRecMutex");
put("GLib.IOFunc", "org/gnome/gir/gobject/GIOFunc");
+ put("GLib.SourceFunc", "org/gnome/gir/gobject/GSourceFunc");
String[] glibPointerUnmapped = new String[] { "Mutex", "Cond", "FreeFunc", "DestroyNotify", "MarkupParser",
- "SpawnChildSetupFunc", "SourceFunc", "Node", "CompareFunc", "KeyFile", "PtrArray", "Func",
+ "SpawnChildSetupFunc", "Node", "CompareFunc", "KeyFile", "PtrArray", "Func",
"ThreadPool", "Source", "CompareDataFunc", "Array", "Data", "DataSet", "Date", "IOChannel" };
for (String unmapped : glibPointerUnmapped)
put("GLib." + unmapped, "com/sun/jna/Pointer");
@@ -99,6 +100,7 @@
put("GObject.ParamSpec", "org/gnome/gir/gobject/GObjectAPI$GParamSpec");
put("GObject.Parameter", "org/gnome/gir/gobject/GObjectAPI$GParameter");
put("GObject.Object", "org/gnome/gir/gobject/GObject");
+ put("GObject.Callback", "com/sun/jna/Callback");
put("GObject.InitiallyUnowned", "org/gnome/gir/gobject/GInitiallyUnowned");
put("GObject.Type", "org/gnome/gir/gobject/GType");
put("GObject.Value", "org/gnome/gir/gobject/GValue");
@@ -124,7 +126,7 @@
put("GObject.FlagsValue", "org/gnome/gir/gobject/GObjectAPI$GFlagsValue");
put("GObject.FlagsClass", "org/gnome/gir/gobject/GObjectAPI$GFlagsClass");
- String[] gobjectUnmapped = new String[] { "Callback", "BaseInitFunc", "InstanceInitFunc",
+ String[] gobjectUnmapped = new String[] { "BaseInitFunc", "InstanceInitFunc",
"SignalAccumulator", "ClosureMarshal", "ClassInitFunc", "SignalEmissionHook",
"IOChannel", "Date", "BaseFinalizeFunc", "ClassFinalizeFunc", "ValueArray" };
for (String unmapped : gobjectUnmapped)
Modified: trunk/src/org/gnome/gir/gobject/GlibAPI.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GlibAPI.java (original)
+++ trunk/src/org/gnome/gir/gobject/GlibAPI.java Thu Oct 23 03:15:12 2008
@@ -114,11 +114,7 @@
void g_thread_set_priority(Pointer thread, int priority);
void g_thread_exit(Pointer retval);
-
-
- interface GSourceFunc extends Callback {
- boolean callback(Pointer data);
- }
+
NativeLong g_idle_add(GSourceFunc function, Pointer data);
interface GDestroyNotify extends Callback {
void callback(Pointer data);
@@ -128,6 +124,7 @@
int g_timeout_add_full(int priority, int interval, GSourceFunc function,
Pointer data, GDestroyNotify notify);
int g_timeout_add_seconds(int interval, GSourceFunc function, Pointer data);
+ int g_timeout_add_seconds_full(int priority, int interval, GSourceFunc function, Pointer data, GDestroyNotify destroy);
void g_error_free(Pointer error);
void g_error_free(GErrorStruct error);
Added: trunk/src/org/gnome/gir/gobject/GlibRuntime.java
==============================================================================
--- (empty file)
+++ trunk/src/org/gnome/gir/gobject/GlibRuntime.java Thu Oct 23 03:15:12 2008
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008 Colin Walters <walters verbum org>
+ *
+ * This file is part of java-gobject-introspection.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307 USA.
+ *
+ */
+
+package org.gnome.gir.gobject;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.sun.jna.Callback;
+import com.sun.jna.Pointer;
+
+public class GlibRuntime {
+ private static final class CallbackData {
+ Callback callback;
+ GlibAPI.GDestroyNotify destroy;
+ }
+ /*
+ * We want to hold a strong reference to both the callback and the destroy
+ * notify, until the notify is called.
+ */
+ private static final Set<CallbackData> outstandingCallbacks
+ = Collections.synchronizedSet(new HashSet<CallbackData>());
+
+ public static final GlibAPI.GDestroyNotify createDestroyNotify(Callback callback) {
+ final CallbackData data = new CallbackData();
+ GlibAPI.GDestroyNotify destroy = new GlibAPI.GDestroyNotify() {
+ @Override
+ public void callback(Pointer data) {
+ outstandingCallbacks.remove(data);
+ }
+ };
+ data.callback = callback;
+ data.destroy = destroy;
+ outstandingCallbacks.add(data);
+ return destroy;
+ }
+}
Modified: trunk/src/org/gnome/gir/gobject/MainLoop.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/MainLoop.java (original)
+++ trunk/src/org/gnome/gir/gobject/MainLoop.java Thu Oct 23 03:15:12 2008
@@ -54,7 +54,6 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
-import org.gnome.gir.gobject.GlibAPI.GSourceFunc;
import com.sun.jna.Pointer;
@@ -219,7 +218,7 @@
public boolean callback(Pointer data) {
try {
r.run();
- } catch (Throwable e) {
+ } catch (Exception e) {
Thread.currentThread().getUncaughtExceptionHandler()
.uncaughtException(Thread.currentThread(), e);
} finally {
@@ -234,7 +233,8 @@
private int rawInvokeLater(final Runnable r) {
GSourceFunc func = sourceFuncForRunnable(r, null);
- return GlibAPI.glib.g_timeout_add(0, func, null);
+ GlibAPI.GDestroyNotify destroy = GlibRuntime.createDestroyNotify(func);
+ return GlibAPI.glib.g_timeout_add_full(0, 0, func, null, destroy);
}
/**
@@ -255,11 +255,12 @@
handle.setComplete();
}
});
+ GlibAPI.GDestroyNotify destroy = GlibRuntime.createDestroyNotify(func);
int id;
if (units.equals(TimeUnit.SECONDS)) {
- id = GlibAPI.glib.g_timeout_add_seconds(timeout, func, null);
+ id = GlibAPI.glib.g_timeout_add_seconds_full(0, timeout, func, null, destroy);
} else {
- id = GlibAPI.glib.g_timeout_add((int) units.toMillis(timeout), func, null);
+ id = GlibAPI.glib.g_timeout_add_full(0, (int) units.toMillis(timeout), func, null, destroy);
}
handle.srcId = id;
return handle;
Modified: trunk/stub-examples/Test.java
==============================================================================
--- trunk/stub-examples/Test.java (original)
+++ trunk/stub-examples/Test.java Thu Oct 23 03:15:12 2008
@@ -33,7 +33,8 @@
}
public int bar(String foo, byte[] bytes) {
- Function target = Internals.library.getFunction("gtk_write_buf");
+ Function target = Internals.library.getFunction("gtk_write_buf");
+
Object[] args = new Object[] { foo, bytes.length, bytes };
Integer result = (Integer) target.invoke(Integer.class, args, Internals.invocationOptions);
return result;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]