Skip to content

Commit

Permalink
Merge pull request #536 from java-native-access/fix-inherited-options
Browse files Browse the repository at this point in the history
Ensure enclosing class query shows up properly for cached options
  • Loading branch information
twall committed Dec 4, 2015
2 parents 0519003 + d6673df commit 900a33c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Features
Bug Fixes
---------
* [#549](https://github.com/java-native-access/jna/pull/549): Fixed bug in types derived from XID - [@twall](https://github.com/twall).
* [#536](https://github.com/java-native-access/jna/pull/536): Fixed bug in determining the Library and options associated with types defined outside of a Library - [@twall](https://github.com/twall).

Release 4.2.1
=============
Expand Down
12 changes: 10 additions & 2 deletions src/com/sun/jna/Native.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public final class Native implements Version {
static String jnidispatchPath = null;
private static Map options = new WeakHashMap();
private static Map libraries = new WeakHashMap();
private static final String _OPTION_ENCLOSING_LIBRARY = "enclosing-library";
private static final UncaughtExceptionHandler DEFAULT_HANDLER =
new UncaughtExceptionHandler() {
@Override
Expand Down Expand Up @@ -549,6 +550,11 @@ static Class findEnclosingLibraryClass(Class cls) {
// implement com.sun.jna.Library.
synchronized(libraries) {
if (options.containsKey(cls)) {
Map libOptions = (Map)options.get(cls);
Class enclosingClass = (Class)libOptions.get(_OPTION_ENCLOSING_LIBRARY);
if (enclosingClass != null) {
return enclosingClass;
}
return cls;
}
}
Expand Down Expand Up @@ -620,7 +626,7 @@ public static Map getLibraryOptions(Class type) {
if (!libraryOptions.containsKey(Library.OPTION_STRING_ENCODING)) {
libraryOptions.put(Library.OPTION_STRING_ENCODING, lookupField(mappingClass, "STRING_ENCODING", String.class));
}
options.put(mappingClass, libraryOptions);
libraryOptions = cacheOptions(mappingClass, libraryOptions, null);
// Store the original lookup class, if different from the mapping class
if (type != mappingClass) {
options.put(type, libraryOptions);
Expand Down Expand Up @@ -1677,8 +1683,9 @@ else if (cvt[t] == CVT_TYPE_MAPPER
/** Take note of options used for a given library mapping, to facilitate
looking them up later.
*/
private static void cacheOptions(Class cls, Map libOptions, Object proxy) {
private static Map cacheOptions(Class cls, Map libOptions, Object proxy) {
libOptions = new HashMap(libOptions);
libOptions.put(_OPTION_ENCLOSING_LIBRARY, cls);
synchronized(libraries) {
options.put(cls, libOptions);
if (proxy != null) {
Expand All @@ -1699,6 +1706,7 @@ private static void cacheOptions(Class cls, Map libOptions, Object proxy) {
}
}
}
return libOptions;
}

private static native long registerMethod(Class cls,
Expand Down
27 changes: 20 additions & 7 deletions test/com/sun/jna/NativeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,6 @@ public void testOptionsInferenceFromInstanceField() {
Class[] classes = { TestInterfaceWithInstance.class, TestInterfaceWithInstance.TestStructure.class };
String[] desc = { "interface", "structure from interface" };
for (int i=0;i < classes.length;i++) {
assertEquals("Wrong options found for " + desc[i]
+ " which provides an instance",
TestInterfaceWithInstance.TEST_OPTS,
Native.getLibraryOptions(classes[i]));
assertEquals("Wrong type mapper found for " + desc[i],
TestInterfaceWithInstance.TEST_MAPPER,
Native.getTypeMapper(classes[i]));
Expand All @@ -236,9 +232,6 @@ abstract class TestStructure extends Structure {}
public void testOptionsInferenceFromOptionsField() {
Class[] classes = { TestInterfaceWithOptions.class, TestInterfaceWithOptions.TestStructure.class };
for (int i=0;i < classes.length;i++) {
assertEquals("Wrong options found for interface which provides OPTIONS",
TestInterfaceWithOptions.OPTIONS,
Native.getLibraryOptions(classes[i]));
assertEquals("Wrong type mapper found",
TestInterfaceWithOptions.TEST_MAPPER,
Native.getTypeMapper(classes[i]));
Expand Down Expand Up @@ -291,6 +284,26 @@ public void testOptionsInferenceFromEncodingField() {
Native.getStringEncoding(TestInterfaceWithEncoding.TestStructure.class));
}

public interface OptionsBase extends Library {
int STRUCTURE_ALIGNMENT = Structure.ALIGN_NONE;
TypeMapper TYPE_MAPPER = new DefaultTypeMapper();
class TypeMappedStructure extends Structure {
public String stringField;
protected List getFieldOrder() { return Arrays.asList("stringField"); }
}
}
public interface OptionsSubclass extends OptionsBase, Library {
TypeMapper _MAPPER = new DefaultTypeMapper();
Map _OPTIONS = new HashMap() { { put(Library.OPTION_TYPE_MAPPER, _MAPPER); } };
OptionsSubclass INSTANCE = (OptionsSubclass)Native.loadLibrary("testlib", OptionsSubclass.class, _OPTIONS);
}
public void testStructureOptionsInference() {
Structure s = new OptionsBase.TypeMappedStructure();
assertEquals("Wrong structure alignment for base structure",
Structure.ALIGN_NONE, Native.getStructureAlignment(s.getClass()));
assertEquals("Wrong type mapper for base structure", OptionsBase.TYPE_MAPPER, s.getTypeMapper());
}

public void testCharArrayToString() {
char[] buf = { 'a', 'b', 'c', '\0', 'd', 'e' };
assertEquals("Wrong String generated", "abc", Native.toString(buf));
Expand Down

0 comments on commit 900a33c

Please sign in to comment.