【问题标题】:How to create a Java Library (API) with native code via JNI如何通过 JNI 使用本机代码创建 Java 库 (API)
【发布时间】:2015-11-23 02:51:29
【问题描述】:

我的问题如下。

我需要用 Java 创建一个库。到目前为止,一切都很好。 像任何体面的 Java 库一样,它必须可以在任何 JVM 上使用。

但是这里的困难在于这个库会包含很多原生代码

我对@9​​87654324@ 有一些了解。 我尝试在带有Android StudioAndroid NDK 的Android 应用程序中用Java 创建一些native 方法。

太好了,我可以做很多 HelloWorld 示例。但是如何将其导出为库?

我的项目需要外部 C++ 库。 我想包装这些库,并在包装​​在 Java 库中的 JNI 包装器中使用它们。

请参阅以下架构:

为了让事情变得更简单,我们以一个简单的 HelloWorld JNI API 为例。 创建一个 Java 桌面应用程序(或其他任何东西)。导入Helloworld JNI API(作为jar),调用String HelloWorldJNI_API.sayHello(String yourName)并打印结果。

这里需要什么:

  1. JNI API 显然会将 sayHello() 方法声明为 本机方法;
  2. 参数 (String yourName) 被发送到 JNI ;
  3. JNI 代码调用内部出色的 C++ so 库,该库处理数据并返回“hello”+“yourName”(太棒了,对吗?)
  4. JNI 代码将结果作为jstring 返回
  5. 最后,Java API 返回结果为String 瞧!

这个简单的例子应该告诉你我想要做什么。

【问题讨论】:

  • 您在哪方面需要帮助?谷歌展示了很多例子; Oracles Java 教程包括一步一步的精细操作。
  • 我确实找到了一些很好的教程(主要针对 Android Studio 和 Netbeans),但它们是特定于平台的,这很有意义,但也限制了我。我需要与尽可能多的平台兼容。像 POJO '^^
  • JNI 库的 Java 部分在每个平台上都是相同的,但本机代码部分必须为您支持的每个平台单独编译。如果您查看“loadLibrary()”方法的工作原理,您会发现您只提供了库名称的根,Java 会计算出每个平台上的文件名。
  • JNA 抽象原生位,以便您可以专注于编写 Java 代码。在大多数平台上,jar 文件 JNA 配置文件 (jna.jar) 知道如何从 jar 文件本身解压和加载本机库。

标签: java android c++ api java-native-interface


【解决方案1】:

好吧,您的库将包含带有 java 包装器代码的 .jar 文件以及本机文件(如果您基于 linux,则为 .so,如果您使用 Windows,则为 .dll)。

这里是乐趣的开始:

因为 native 是用处理器汇编语言编译的,所以您必须为所有受支持的目标编译 .so(例如,对于所有具有 native 支持的 android,因为就像永远一样): armv5、armv7、armv7s、arm64

现在,您必须提供包含上述所有内容的存档。

在这种情况下,您需要一个独立的库,而不向开发人员提供代码。

如果你能提供代码,那么你就不用担心不同的架构了。

【讨论】:

  • 谢谢!我知道它会是那样的。但是在哪里可以找到完成这么多的工具和指南呢?我需要一个独立的库。代码肯定会被混淆(意味着外部开发人员应该无法访问)。那么我应该如何创建这个 API 呢?我可以使用 Netbeans IDE 并创建 C/C++ 库吗?如何为所有这些平台导出它?
  • 使用 JNI 进行分配的建议:使用 C++ 的 IDE 创建本机部分,然后使用 Java/Android 的 IDE 测试包装器。不要错误地将 Eclipse /Net Beans / InteliJ 用于本机......你最好使用记事本++和编译器。您需要考虑的第二件事:在桌面上工作时,使用与 java 包装器等效的 C++ 包装器进行调试,以便在桌面上进行测试。这将为您提供断点,并为您省去在拥有 java 入口点时尝试调试本机代码的令人难以置信的头痛:)。
  • 等等,我可以在 notepad++ 中调试 C++ 代码吗?为什么我不应该将 Netbeans 用于 native ?我也可以调试本机代码。最后,按照您的指示,我最终会在 notepad++ 和 Android Studio 之间复制和粘贴代码?
  • 根据我使用Eclipse的经验,问题是入口点在java中,所以调试器必须切换(有一个java调试器和一个本地调试器),在Eclipse中这非常有效很糟糕(更像是它不起作用)。 Notepad++ 不附带调试器,我说我更喜欢使用 Notepad++ 而不是使用带有 C++ 的 Eclipse(自动完成效果不好,notepad++ 更轻量级等)。您最终不会粘贴代码。当您在桌面上进行调试时,您将拥有一个 C++ 入口点,而当您在真实事物上进行测试时,您将拥有一个 Java 入口点。
  • 我不喜欢 Eclipse。我刚刚尝试了 Netbeans C++ 调试器(当然使用 gdb),它工作正常。自动补全。无论如何,我应该在哪里编写这个 C++ 包装器(入口点)?调试器怎么会附加到代码上?感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多