diff --git a/CHANGES.md b/CHANGES.md index 53e15754a0..bfa1bba0d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,7 @@ Features * [#997](https://github.com/java-native-access/jna/issues/997): Added `Sysinfo` structure and function to `c.s.j.platform.linux.LibC` - [@dbwiddis](https://github.com/dbwiddis). * [#1001](https://github.com/java-native-access/jna/pull/1001): Added overloads to `c.s.j.platform.win32.Advapi32Util` methods which allow the caller to specify `samDesiredExtra` to request additional registry key security and access rights - [@camw](https://github.com/camw). * [#1007](https://github.com/java-native-access/jna/pull/1007): Added OSGi export of Solaris package - [@swimmesberger](https://github.com/swimmesberger). +* [#1003](https://github.com/java-native-access/jna/pull/1003): Allow `NativeMapped` to be used with enums - [@koraktor](https://github.com/koraktor). Bug Fixes --------- diff --git a/src/com/sun/jna/NativeMappedConverter.java b/src/com/sun/jna/NativeMappedConverter.java index c2cd5e5789..d91baa6973 100644 --- a/src/com/sun/jna/NativeMappedConverter.java +++ b/src/com/sun/jna/NativeMappedConverter.java @@ -57,6 +57,10 @@ public NativeMappedConverter(Class type) { } public NativeMapped defaultValue() { + if (type.isEnum()) { + return (NativeMapped) type.getEnumConstants()[0]; + } + try { return (NativeMapped)type.newInstance(); } catch (InstantiationException e) { diff --git a/test/com/sun/jna/NativedMappedTest.java b/test/com/sun/jna/NativedMappedTest.java new file mode 100644 index 0000000000..357f6b1474 --- /dev/null +++ b/test/com/sun/jna/NativedMappedTest.java @@ -0,0 +1,108 @@ +/* Copyright (c) 2018 Sebastian Staudt, Matthias Bläsing, All Rights Reserved + * + * The contents of this file is dual-licensed under 2 + * alternative Open Source/Free licenses: LGPL 2.1 or later and + * Apache License 2.0. (starting with JNA version 4.0.0). + * + * You can freely decide which license you want to apply to + * the project. + * + * You may obtain a copy of the LGPL License at: + * + * http://www.gnu.org/licenses/licenses.html + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "LGPL2.1". + * + * You may obtain a copy of the Apache License at: + * + * http://www.apache.org/licenses/ + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "AL2.0". + */ +package com.sun.jna; + +import junit.framework.TestCase; +import static junit.framework.TestCase.assertEquals; + +public class NativedMappedTest extends TestCase { + + public void testDefaultValueForClass() { + NativeMappedConverter converter = new NativeMappedConverter(NativeMappedTestClass.class); + + assertTrue(converter.defaultValue() instanceof NativeMappedTestClass); + } + + public void testDefaultValueForEnum() { + NativeMappedConverter converter = new NativeMappedConverter(TestEnum.class); + + assertSame(converter.defaultValue(), TestEnum.VALUE1); + } + + public static interface EnumerationTestLibrary extends Library { + TestEnum returnInt32Argument(TestEnum arg); + + @Structure.FieldOrder({"field"}) + class MinTestStructure extends Structure { + public TestEnum field; + } + MinTestStructure testStructurePointerArgument(MinTestStructure s); + } + + public void testEnumConversion() throws Exception { + EnumerationTestLibrary lib = Native.load("testlib", EnumerationTestLibrary.class); + assertEquals("Enumeration improperly converted", TestEnum.VALUE1, lib.returnInt32Argument(TestEnum.VALUE1)); + assertEquals("Enumeration improperly converted", TestEnum.VALUE2, lib.returnInt32Argument(TestEnum.VALUE2)); + EnumerationTestLibrary.MinTestStructure struct = new EnumerationTestLibrary.MinTestStructure(); + struct.field = TestEnum.VALUE1; + assertEquals("Enumeration in structure improperly converted", TestEnum.VALUE1, lib.testStructurePointerArgument(struct).field); + struct.field = TestEnum.VALUE2; + assertEquals("Enumeration in structure improperly converted", TestEnum.VALUE2, lib.testStructurePointerArgument(struct).field); + } + + public enum TestEnum implements NativeMapped { + VALUE1, VALUE2; + + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + return values()[(Integer) nativeValue]; + } + + @Override + public Object toNative() { + return ordinal(); + } + + @Override + public Class nativeType() { + return Integer.class; + } + } + + public static class NativeMappedTestClass implements NativeMapped { + + private String name; + + public NativeMappedTestClass() { + } + + @Override + public Object fromNative(Object nativeValue, FromNativeContext context) { + NativeMappedTestClass object = new NativeMappedTestClass(); + object.name = (String) nativeValue; + + return object; + } + + @Override + public Object toNative() { + return name; + } + + @Override + public Class nativeType() { + return String.class; + } + } +}