Skip to content

Commit d6673df

Browse files
committed
ensure enclosing class query shows up properly for cached options
1 parent 0519003 commit d6673df

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Features
2424
Bug Fixes
2525
---------
2626
* [#549](https://github.com/java-native-access/jna/pull/549): Fixed bug in types derived from XID - [@twall](https://github.com/twall).
27+
* [#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).
2728

2829
Release 4.2.1
2930
=============

src/com/sun/jna/Native.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public final class Native implements Version {
103103
static String jnidispatchPath = null;
104104
private static Map options = new WeakHashMap();
105105
private static Map libraries = new WeakHashMap();
106+
private static final String _OPTION_ENCLOSING_LIBRARY = "enclosing-library";
106107
private static final UncaughtExceptionHandler DEFAULT_HANDLER =
107108
new UncaughtExceptionHandler() {
108109
@Override
@@ -549,6 +550,11 @@ static Class findEnclosingLibraryClass(Class cls) {
549550
// implement com.sun.jna.Library.
550551
synchronized(libraries) {
551552
if (options.containsKey(cls)) {
553+
Map libOptions = (Map)options.get(cls);
554+
Class enclosingClass = (Class)libOptions.get(_OPTION_ENCLOSING_LIBRARY);
555+
if (enclosingClass != null) {
556+
return enclosingClass;
557+
}
552558
return cls;
553559
}
554560
}
@@ -620,7 +626,7 @@ public static Map getLibraryOptions(Class type) {
620626
if (!libraryOptions.containsKey(Library.OPTION_STRING_ENCODING)) {
621627
libraryOptions.put(Library.OPTION_STRING_ENCODING, lookupField(mappingClass, "STRING_ENCODING", String.class));
622628
}
623-
options.put(mappingClass, libraryOptions);
629+
libraryOptions = cacheOptions(mappingClass, libraryOptions, null);
624630
// Store the original lookup class, if different from the mapping class
625631
if (type != mappingClass) {
626632
options.put(type, libraryOptions);
@@ -1677,8 +1683,9 @@ else if (cvt[t] == CVT_TYPE_MAPPER
16771683
/** Take note of options used for a given library mapping, to facilitate
16781684
looking them up later.
16791685
*/
1680-
private static void cacheOptions(Class cls, Map libOptions, Object proxy) {
1686+
private static Map cacheOptions(Class cls, Map libOptions, Object proxy) {
16811687
libOptions = new HashMap(libOptions);
1688+
libOptions.put(_OPTION_ENCLOSING_LIBRARY, cls);
16821689
synchronized(libraries) {
16831690
options.put(cls, libOptions);
16841691
if (proxy != null) {
@@ -1699,6 +1706,7 @@ private static void cacheOptions(Class cls, Map libOptions, Object proxy) {
16991706
}
17001707
}
17011708
}
1709+
return libOptions;
17021710
}
17031711

17041712
private static native long registerMethod(Class cls,

test/com/sun/jna/NativeTest.java

+20-7
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,6 @@ public void testOptionsInferenceFromInstanceField() {
206206
Class[] classes = { TestInterfaceWithInstance.class, TestInterfaceWithInstance.TestStructure.class };
207207
String[] desc = { "interface", "structure from interface" };
208208
for (int i=0;i < classes.length;i++) {
209-
assertEquals("Wrong options found for " + desc[i]
210-
+ " which provides an instance",
211-
TestInterfaceWithInstance.TEST_OPTS,
212-
Native.getLibraryOptions(classes[i]));
213209
assertEquals("Wrong type mapper found for " + desc[i],
214210
TestInterfaceWithInstance.TEST_MAPPER,
215211
Native.getTypeMapper(classes[i]));
@@ -236,9 +232,6 @@ abstract class TestStructure extends Structure {}
236232
public void testOptionsInferenceFromOptionsField() {
237233
Class[] classes = { TestInterfaceWithOptions.class, TestInterfaceWithOptions.TestStructure.class };
238234
for (int i=0;i < classes.length;i++) {
239-
assertEquals("Wrong options found for interface which provides OPTIONS",
240-
TestInterfaceWithOptions.OPTIONS,
241-
Native.getLibraryOptions(classes[i]));
242235
assertEquals("Wrong type mapper found",
243236
TestInterfaceWithOptions.TEST_MAPPER,
244237
Native.getTypeMapper(classes[i]));
@@ -291,6 +284,26 @@ public void testOptionsInferenceFromEncodingField() {
291284
Native.getStringEncoding(TestInterfaceWithEncoding.TestStructure.class));
292285
}
293286

287+
public interface OptionsBase extends Library {
288+
int STRUCTURE_ALIGNMENT = Structure.ALIGN_NONE;
289+
TypeMapper TYPE_MAPPER = new DefaultTypeMapper();
290+
class TypeMappedStructure extends Structure {
291+
public String stringField;
292+
protected List getFieldOrder() { return Arrays.asList("stringField"); }
293+
}
294+
}
295+
public interface OptionsSubclass extends OptionsBase, Library {
296+
TypeMapper _MAPPER = new DefaultTypeMapper();
297+
Map _OPTIONS = new HashMap() { { put(Library.OPTION_TYPE_MAPPER, _MAPPER); } };
298+
OptionsSubclass INSTANCE = (OptionsSubclass)Native.loadLibrary("testlib", OptionsSubclass.class, _OPTIONS);
299+
}
300+
public void testStructureOptionsInference() {
301+
Structure s = new OptionsBase.TypeMappedStructure();
302+
assertEquals("Wrong structure alignment for base structure",
303+
Structure.ALIGN_NONE, Native.getStructureAlignment(s.getClass()));
304+
assertEquals("Wrong type mapper for base structure", OptionsBase.TYPE_MAPPER, s.getTypeMapper());
305+
}
306+
294307
public void testCharArrayToString() {
295308
char[] buf = { 'a', 'b', 'c', '\0', 'd', 'e' };
296309
assertEquals("Wrong String generated", "abc", Native.toString(buf));

0 commit comments

Comments
 (0)