在Android上从Java调用C类方法或函数,而不是在每次调用时重新创建类/变量

前端之家收集整理的这篇文章主要介绍了在Android上从Java调用C类方法或函数,而不是在每次调用时重新创建类/变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个非常复杂的NLP代码写在C上,现在我想从我的 Android应用程序中使用它.我的想法是使用客户端 – 服务器架构构建应用程序,其中客户端是一个android java应用程序,而服务器是一个C面向对象的代码.但对我来说主要的问题是,C组件非常繁重(标记器,矢量化器,语料库数据等),我无法在每次调用时重新创建它们,我需要的是创建它们一次(在第一次请求时),然后将它们放在内存中,当应用程序处于活动状态时,来自java端的handlind请求.

你能不能给我一些如何实现这一点的指导,因为我以前从未使用过Android的C?提前致谢.

Java和C代码不是远程的,没有涉及http或其他远程请求,它是相同的应用程序.但是为了减少Java / C通信间的开销,我不想在java代码中有单点联系,比如NlpEngine.sendRequest(string textToProcess,int processingWorkflowId)然后C代码基于processingWorkflowId识别,它是什么呢应该用文字.

解决方法

Assumtion

我假设您使用Android NDK等工具集为Android编译了C代码,并且前端Java应用程序与后端C代码在同一设备上运行.

Java本机调用和会话状态

无论您使用以下三个接口中的哪一个.在Java应用程序运行的整个过程中,C/C++库被加载并保留在内存中.图书馆的状态将一直保存.我没有清楚地了解你对初始化的担忧.这不像在CLI上启动命令,其他应用程序一次又一次地启动和停止.

… But main problem for me,is that C++ components are pretty heavy (tokenizers,vectorizers,corpus data,etc) and I can’t recreate them on every call …

用Java加载本机库

有一些方法可以用Java加载本机库,我想指出三点:

> JNI – Java Native Interface

JNI是一个与Java本身一样古老的工具.来自SWT的系统调用是使用JNI创建的. JNI不是简单的方法,您必须将要在Java中创建的函数/方法定义为本机,将它们编译为C/C++头,编写用于在此中间库中调用库的代码.为每个ABI平台编译此代码(There are 7 Androids ABIs according to NDK).在Java程序中,您已找到调用ABI合适中间库的平台. JNI还有许多其他陷阱.
> JNA – Java Native Access

[JNA]是一个通过反射动态加载C/C++库的java库. Java调用的定义是在纯Java中完成的,没有额外的工具.易用性在性能上有所折衷,调用函数的开销比JNI慢10倍.但是,如果你经常调用极短的C/C++库函数/方法,那只会起作用.在你的情况下,听起来你只需要调用一些函数,这些函数将需要时间来运行. JNA由Android开发人员使用.
> JNR-FFI – Java Native Runtime

JNR-FFI是最新的候选人. JNR-FFI是用于调用库的部分.其他部分是JNR-FFI的基线.它受到了JNA的启发.使用JNA和JNR-FFI开发的Java代码看起来非常相似. JNR-FFI开发的原因是性能.一般来说,JNR-FFI比JNI慢一点(对于getpid大约15%)但在某些情况下它可能比JNI快.对于C/C++端的长运行时,这种开销并不重要. JNR被提议在Java 9中作为标准库JEP 191: Foreign Function Interface.警告:JNR-FFI接缝与Android有一些问题.

个人经验

我不得不从Java实现一些本机库调用.我从JNI开始,经过一周的测试研究,只有很少的演示线可以工作.每次尝试都需要很长时间,不同的工具,建设时间长.我找到了关于JNI陷阱的演示文稿以及必须考虑的副作用. …

我找到了JNA.在几个小时内,我的库的第一个演示代码工作,并与JNI进行比较,它是如此轻量级和快速开发.我切换到JNR-FFI,因为它是JNA的现代版本.对于我所做的,性能不是切换的原因,这只是一个积极的副作用.

我没有在Android下用JNA或JNR-FFI开发.但在你的情况下,我会尝试JNA,因为它更好地支持Android.我希望JNR-FFI在Java 9中实现,从JNA代码切换到JNR-FFI代码很容易.

添加了JNR-FFI的示例,让您了解易用性.除了实现这几行以便能够调用本机c库函数之外,没有什么比这更多的了.

JNR-FFI取自Java Native Runtime – The Missing Link by Charles Oliver Nutter的示例

public class GetPidJNRExample {
    public interface GetPid {
        @IgnoreError
        long getpid();
    }

    public static void main( String[] args ) {
        LibraryLoader<GetPid> loader =
            FFIProvider
                .getSystemProvider()
                .createLibraryLoader(GetPid.class);

        GetPid getpid = loader.load("c");

        getpid.getpid();
    }
}

猜你在找的Android相关文章