Skip to content

Commit

Permalink
Merge pull request #1615 from matthiasblaesing/issue-1613
Browse files Browse the repository at this point in the history
Add Native#getNativeLibrary to get access to library wrapped by Native#load or Native#register
  • Loading branch information
matthiasblaesing authored Jul 6, 2024
2 parents 4f94c57 + bd05b75 commit a587921
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Features
* [#1593](https://github.com/java-native-access/jna/pull/1593): Add support for DragonFly BSD x86-64 - [@liweitianux](https://github.com/liweitianux).
* [#1595](https://github.com/java-native-access/jna/pull/1595): Add `IsProcessorFeaturePresent` to `c.s.j.p.win32.Kernel32` - [@dbwiddis](https://github.com/dbwiddis).
* [#1602](https://github.com/java-native-access/jna/pull/1602): Add `XMoveWindow`, `XResizeWindow`, `XMoveResizeWindow`, `XRaiseWindow`, `XLowerWindow` X11 calls to `c.s.j.p.unix.X11` - [@vinceh121](https://github.com/vinceh121).
* [#1613](https://github.com/java-native-access/jna/issues/1613): Added static helper method `Native#getNativeLibrary' for getting the underlying NativeLibrary instance from a Library interface instance or from a "registered" class - [@matthiasblaesing](https://github.com/matthiasblaesing).

Bug Fixes
---------
Expand Down
46 changes: 46 additions & 0 deletions src/com/sun/jna/Native.java
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,52 @@ public static void register(Class<?> cls, NativeLibrary lib) {
}
}

/**
* Get the {@link NativeLibrary} instance that is wrapped by the given
* {@link Library} interface instance.
*
* @param library the {@link Library} interface instance, which was created
* by the {@link Native#load Native.load()} method
* @return the wrapped {@link NativeLibrary} instance
*/
public static NativeLibrary getNativeLibrary(final Library library) {
if(library == null) {
throw new IllegalArgumentException("null passed to getNativeLibrary");
}
if(! Proxy.isProxyClass(library.getClass())) {
throw new IllegalArgumentException("library object passed to getNativeLibrary in not a proxy");
}
final InvocationHandler handler = Proxy.getInvocationHandler(library);
if (!(handler instanceof Library.Handler)) {
throw new IllegalArgumentException("Object is not a properly initialized Library interface instance");
}
return ((Library.Handler) handler).getNativeLibrary();
}

/**
* Get the {@link NativeLibrary} instance to which the given "registered"
* class is bound.
*
* @param cls the "registered" class, which was previously registered via
* the {@link Native#register register()} method
* @return the {@link NativeLibrary} instance to which the "registered"
* class is bound
*/
public static NativeLibrary getNativeLibrary(final Class<?> cls) {
if(cls == null) {
throw new IllegalArgumentException("null passed to getNativeLibrary");
}
final Class<?> mappedClass = findDirectMappedClass(cls);
synchronized(registeredClasses) {
final NativeLibrary nativeLibrary = registeredLibraries.get(mappedClass);
if (nativeLibrary == null) {
throw new IllegalArgumentException("Class " + cls.getName() + " is not currently registered");
} else {
return nativeLibrary;
}
}
}

/* Take note of options used for a given library mapping, to facilitate
* looking them up later.
*/
Expand Down
94 changes: 94 additions & 0 deletions test/com/sun/jna/NativeGetNativeLibraryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Copyright (c) 2024 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 java.util.Collections;
import junit.framework.TestCase;

/**
* Check getNativeLibrary functions in Native
*/
public class NativeGetNativeLibraryTest extends TestCase {

private NativeLibrary libUTF8;
private TestLib libUTF8Interface;

@Override
protected void setUp() {
libUTF8 = NativeLibrary.getInstance("testlib",
Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8"));
Native.register(TestLibUTF8.class, libUTF8);
libUTF8Interface = Native.load("testlib", TestLib.class,
Collections.singletonMap(Library.OPTION_STRING_ENCODING, "UTF-8"));
}

public void testGetNativeLibraryInterface() {
NativeLibrary nl = Native.getNativeLibrary(libUTF8Interface);
assertTrue(nl instanceof NativeLibrary);
}

public void testGetNativeLibraryDirect() {
NativeLibrary nl = Native.getNativeLibrary(TestLibUTF8.class);
assertTrue(nl instanceof NativeLibrary);
// This only makes sense for the direct case, as that directly wraps
// a supplied instance
assertEquals(libUTF8, nl);
}

public void testGetNativeLibraryOnUnboundShouldFail() {
try {
Native.getNativeLibrary(new TestLib() {
@Override
public String returnStringArgument(Pointer input) {
return "";
}
});
assertTrue("Exception not thrown", false);
} catch (IllegalArgumentException ex) {
// This should be reached
}
}

public void testGetNativeLibraryOnNullShouldFail() {
try {
Native.getNativeLibrary((Class) null);
assertTrue("Exception not thrown", false);
} catch (IllegalArgumentException ex) {
// This should be reached
}
}

public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(NativeGetNativeLibraryTest.class);
}

private static class TestLibUTF8 implements Library {
native String returnStringArgument(Pointer input);
}

private interface TestLib extends Library {
public String returnStringArgument(Pointer input);
}

}

0 comments on commit a587921

Please sign in to comment.