Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

}