diff --git a/native/dispatch.c b/native/dispatch.c index a79d688b..755c2316 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 e4078982..24df5a74 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 70999bb4..b46311e2 100644 --- a/src/com/sun/jna/DefaultTypeMapper.java +++ b/src/com/sun/jna/DefaultTypeMapper.java @@ -117,7 +117,7 @@ public class DefaultTypeMapper implements TypeMapper { /** 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 034b5727..cd79f9eb 100644 --- a/test/com/sun/jna/DirectTypeMapperTest.java +++ b/test/com/sun/jna/DirectTypeMapperTest.java @@ -13,10 +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.util.HashMap; import java.util.Map; import junit.framework.TestCase; @@ -156,6 +152,42 @@ public class DirectTypeMapperTest extends TestCase { 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 PointTestClass returnPoint(int x, int y); + static { + Map options = new HashMap(); + DefaultTypeMapper mapper = new DefaultTypeMapper(); + mapper.addTypeConverter(PointTestClass.class, new TypeConverter() { + public Object fromNative(Object value, FromNativeContext context) { + Pointer p = (Pointer) value; + PointTestClass pc = new PointTestClass(); + pc.x = p.getInt(0); + pc.y = p.getInt(4); + Native.free(Pointer.nativeValue(p)); + return pc; + } + 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); + PointTestClass.TYPE_MAPPER = mapper; + Native.register(NativeLibrary.getInstance("testlib", options)); + } + } + public void testTypeMapperResultTypeConversion() throws Exception { + DirectTypeMappedResultTypeTestLibrary lib = new DirectTypeMappedResultTypeTestLibrary(); + 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); + } public static void main(String[] args) { junit.textui.TestRunner.run(DirectTypeMapperTest.class);