你能不能给我一些如何实现这一点的指导,因为我以前从未使用过Android的C?提前致谢.
Java和C代码不是远程的,没有涉及http或其他远程请求,它是相同的应用程序.但是为了减少Java / C通信间的开销,我不想在java代码中有单点联系,比如NlpEngine.sendRequest(string textToProcess,int processingWorkflowId)然后C代码基于processingWorkflowId识别,它是什么呢应该用文字.
解决方法
我假设您使用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(); } }