Java本地运行时深度解析:139章节导读

发表时间: 2024-05-17 03:19

Java本地运行时(JNR)是另一个旨在解决JNI复杂性的开源尝试。它是JNA的有力竞争者,拥有比JNI更直观和强大的API。我们可以按照以下方式将其作为依赖项添加:

<dependency>  <groupId>com.github.jnr</groupId>  <artifactId>jnr-ffi</artifactId>  <version>2.2.13</version></dependency>

假设我们有与问题138中完全相同的C方法(sumTwoInt())和本地共享库(math.dll)。我们首先编写一个包含我们计划从Java调用并在本地代码中定义的方法和类型的声明的Java接口。我们编写包含sumTwoInt()声明的SimpleMath接口如下:

public interface SimpleMath {  @IgnoreError  long sumTwoInt(int x, int y);}

@IgnoreError注解指示JNR不保存errno值(https://www.geeksforgeeks.org/errno-constant-in-c/)。

接下来,我们必须指导JNR加载math.dll库并生成这个接口的具体实现,这样我们就可以调用它的的方法。为此,我们需要LibraryLoader和以下直观的代码:

public class Main {  public static void main(String[] args) {    LibraryLoader<SimpleMath> loader =            FFIProvider.getSystemProvider()   .createLibraryLoader(SimpleMath.class)   .search("./jnr/cpp")   .map("sumTwoInt", "_Z9sumTwoIntii");   loader = loader.map("sumTwoInt", "_Z9sumTwoIntii");      if (Platform.getNativePlatform().getOS()    == Platform.OS.WINDOWS) {    SimpleMath simpleMath = loader.load("math");                              long result = simpleMath.sumTwoInt(3, 9);    System.out.println("Result: " + result);   }  }}

通过LibraryLoader API,我们准备了游乐场。我们指导JNR我们的库位于jnr/cpp,通过search()方法。此外,我们通过map()方法提供方法名称的正确映射(记住从问题138中,G++通过名称混淆(或名称装饰)将方法从sumTwoInt重命名为_Z9sumTwoIntii)。最后,我们通过load()方法加载库并调用sumTwoInt()方法。

JNR提供了许多其他特性,您可以从https://github.com/jnr开始利用。您可能还对JavaCPP感兴趣,它是JNI的另一个替代品(https://github.com/bytedeco/javacpp)。