From d7bb1e189fee9ff0744b6fbee5fd9e262ffa754a Mon Sep 17 00:00:00 2001 From: Taco Date: Tue, 8 Apr 2014 18:23:44 +0200 Subject: [PATCH 1/3] fixed direct-mapping type-mapped pointer result types --- native/dispatch.c | 3 ++ native/testlib.c | 8 ++++ src/com/sun/jna/DefaultTypeMapper.java | 2 +- test/com/sun/jna/DirectTypeMapperTest.java | 44 ++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/native/dispatch.c b/native/dispatch.c index a79d688b53..755c231666 100644 --- a/native/dispatch.c +++ b/native/dispatch.c @@ -1150,6 +1150,9 @@ fromNativeTypeMapped(JNIEnv* env, jobject from_native, void* resp, ffi_type* typ if (type->type != FFI_TYPE_POINTER) { extract_value(env, obj, result, type->size, JNI_TRUE); } + else { + *(jobject*)result = obj; + } } } } diff --git a/native/testlib.c b/native/testlib.c index e40789824a..24df5a747a 100644 --- a/native/testlib.c +++ b/native/testlib.c @@ -158,6 +158,14 @@ returnInt32Argument(int32_t arg) { return arg; } +EXPORT int* +returnPoint(int x, int y) { + int *p = malloc(2 * sizeof(int)); + p[0] = x; + p[1] = y; + return p; +} + EXPORT int64_t returnInt64Zero() { int64_t value = 0; diff --git a/src/com/sun/jna/DefaultTypeMapper.java b/src/com/sun/jna/DefaultTypeMapper.java index 70999bb41b..b46311e205 100644 --- a/src/com/sun/jna/DefaultTypeMapper.java +++ b/src/com/sun/jna/DefaultTypeMapper.java @@ -117,7 +117,7 @@ public void addFromNativeConverter(Class cls, FromNativeConverter converter) { /** Add a {@link TypeConverter} to provide bidirectional mapping between * a native and Java type. */ - protected void addTypeConverter(Class cls, TypeConverter converter) { + public void addTypeConverter(Class cls, TypeConverter converter) { addFromNativeConverter(cls, converter); addToNativeConverter(cls, converter); } diff --git a/test/com/sun/jna/DirectTypeMapperTest.java b/test/com/sun/jna/DirectTypeMapperTest.java index 034b572706..704bcdb398 100644 --- a/test/com/sun/jna/DirectTypeMapperTest.java +++ b/test/com/sun/jna/DirectTypeMapperTest.java @@ -13,10 +13,12 @@ package com.sun.jna; +import java.awt.Point; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; @@ -156,6 +158,48 @@ public void testIntegerToBooleanResultConversion() throws Exception { assertFalse("Failed to convert integer return to boolean FALSE", lib.returnInt32Argument(false)); } + public static class DirectTypeMappedResultTypeTestLibrary { + public native Point returnPoint(int x, int y); + static { + Map options = new HashMap(); + DefaultTypeMapper mapper = new DefaultTypeMapper(); + mapper.addTypeConverter(Point.class, new TypeConverter() { + public Object fromNative(Object value, FromNativeContext context) { + Pointer p = (Pointer) value; + int x = p.getInt(0), y = p.getInt(4); + Native.free(Pointer.nativeValue(p)); + return new Point(x, y); + } + public Object toNative(Object value, ToNativeContext context) { + return Pointer.NULL; // dummy implementation (not called) + } + public Class nativeType() { + return Pointer.class; + } + }); + options.put(Library.OPTION_TYPE_MAPPER, mapper); + + // Can't extend java.awt.Point; can't add: + // public final static TypeMapper TYPE_MAPPER = mapper; + // -> Extend Native.options via reflection: + try { + Field f = Native.class.getDeclaredField("options"); + f.setAccessible(true); + ((Map) f.get(null)).put(Point.class, options); + } + catch (Exception e) { + throw new RuntimeException(e); + } + + Native.register(NativeLibrary.getInstance("testlib", options)); + } + } + public void testTypeMapperResultTypeConversion() throws Exception { + DirectTypeMappedResultTypeTestLibrary lib = new DirectTypeMappedResultTypeTestLibrary(); + Point p = lib.returnPoint(1234, 5678); + assertEquals("Failed to convert int* return to java.awt.Point", 1234, p.x); + assertEquals("Failed to convert int* return to java.awt.Point", 5678, p.y); + } public static void main(String[] args) { junit.textui.TestRunner.run(DirectTypeMapperTest.class); From cfbe750615a39e4bb69c024687bff0b86484a6cf Mon Sep 17 00:00:00 2001 From: Taco Date: Wed, 9 Apr 2014 18:33:31 +0200 Subject: [PATCH 2/3] improved testcase --- test/com/sun/jna/DirectTypeMapperTest.java | 31 +++++++++------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/test/com/sun/jna/DirectTypeMapperTest.java b/test/com/sun/jna/DirectTypeMapperTest.java index 704bcdb398..619f3b4aee 100644 --- a/test/com/sun/jna/DirectTypeMapperTest.java +++ b/test/com/sun/jna/DirectTypeMapperTest.java @@ -13,7 +13,6 @@ package com.sun.jna; -import java.awt.Point; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -158,17 +157,23 @@ public void testIntegerToBooleanResultConversion() throws Exception { assertFalse("Failed to convert integer return to boolean FALSE", lib.returnInt32Argument(false)); } + public static class PointTestClass { + public static TypeMapper TYPE_MAPPER; + int x, y; + } public static class DirectTypeMappedResultTypeTestLibrary { - public native Point returnPoint(int x, int y); + public native PointTestClass returnPoint(int x, int y); static { Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); - mapper.addTypeConverter(Point.class, new TypeConverter() { + mapper.addTypeConverter(PointTestClass.class, new TypeConverter() { public Object fromNative(Object value, FromNativeContext context) { Pointer p = (Pointer) value; - int x = p.getInt(0), y = p.getInt(4); + PointTestClass pc = new PointTestClass(); + pc.x = p.getInt(0); + pc.y = p.getInt(4); Native.free(Pointer.nativeValue(p)); - return new Point(x, y); + return pc; } public Object toNative(Object value, ToNativeContext context) { return Pointer.NULL; // dummy implementation (not called) @@ -178,25 +183,13 @@ public Class nativeType() { } }); options.put(Library.OPTION_TYPE_MAPPER, mapper); - - // Can't extend java.awt.Point; can't add: - // public final static TypeMapper TYPE_MAPPER = mapper; - // -> Extend Native.options via reflection: - try { - Field f = Native.class.getDeclaredField("options"); - f.setAccessible(true); - ((Map) f.get(null)).put(Point.class, options); - } - catch (Exception e) { - throw new RuntimeException(e); - } - + PointTestClass.TYPE_MAPPER = mapper; Native.register(NativeLibrary.getInstance("testlib", options)); } } public void testTypeMapperResultTypeConversion() throws Exception { DirectTypeMappedResultTypeTestLibrary lib = new DirectTypeMappedResultTypeTestLibrary(); - Point p = lib.returnPoint(1234, 5678); + PointTestClass p = lib.returnPoint(1234, 5678); assertEquals("Failed to convert int* return to java.awt.Point", 1234, p.x); assertEquals("Failed to convert int* return to java.awt.Point", 5678, p.y); } From deff187509a5b9736b69a29084136229c88677e4 Mon Sep 17 00:00:00 2001 From: Taco Date: Wed, 9 Apr 2014 18:49:14 +0200 Subject: [PATCH 3/3] removed unused imports --- test/com/sun/jna/DirectTypeMapperTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/com/sun/jna/DirectTypeMapperTest.java b/test/com/sun/jna/DirectTypeMapperTest.java index 619f3b4aee..cd79f9eb27 100644 --- a/test/com/sun/jna/DirectTypeMapperTest.java +++ b/test/com/sun/jna/DirectTypeMapperTest.java @@ -13,11 +13,6 @@ package com.sun.jna; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase;