JNI是java自带的功能,引用也非常简单 System.loadLibrary("libjni");
JNI和JNA不同,JNI的用法比JNA更复杂。libjni
的C++动态库有很多坑需要避免。
首先就是java和C++程序是相互关联的,两者无法完全分离开来。
如果你在java项目中写C++对应的方法名。如下,写sig类里包含的方法:
package src.sig;
public class sig {
public native long importPkey(String str);
public native String newPkey();
public native String GetBase58(long pkey);
public native String GetPubStr(long pkey);
}
写完之后则需要生成对应的sig.h
文件,需要到项目的对应目录下,如上的src.sig
则到src的同级目录下,打开命令行,输入javac -h . sig.java
就会在同级目录下生成src_sig_sig.h
。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class src_sig_sig */
#ifndef _Included_src_sig_sig
#define _Included_src_sig_sig
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: src_sig_sig
* Method: importPkey
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_src_sig_sig_importPkey
(JNIEnv *, jobject, jstring);
/*
* Class: src_sig_sig
* Method: newPkey
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_src_sig_sig_newPkey
(JNIEnv *, jobject);
/*
* Class: src_sig_sig
* Method: GetBase58
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_src_sig_sig_GetBase58
(JNIEnv *, jobject, jlong);
/*
* Class: src_sig_sig
* Method: GetPubStr
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_src_sig_sig_GetPubStr
(JNIEnv *, jobject, jlong);
#ifdef __cplusplus
}
#endif
#endif
生成文件之后,拷贝到C程序对应的目录下。对应的还需要,修改src_sig_sig.cpp
文件的方法名(和.h
方法名相同)。
#include "src_sig_sig.h"
#include "debug.h"
#include "jni.h"
#include "sig.h"
#include "base64.h"
#include <string>
#include "jni_tools.h"
#include "sigTx.h"
/*
* Class: src_sig_sig
* Method: importPkey
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_src_sig_sig_importPkey
(JNIEnv * env, jobject, jstring str){
......//方法实现
}
/*
* Class: src_sig_sig
* Method: newPkey
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_src_sig_sig_newPkey
(JNIEnv *env , jobject){
......
}
JNIEXPORT jstring JNICALL Java_src_sig_sig_GetBase58
(JNIEnv *env , jobject, jlong pkey){
......
}
JNIEXPORT jstring JNICALL Java_src_sig_sig_GetPubStr
(JNIEnv *env, jobject, jlong pkey){
......
}
写完之后,进行C++代码编译。
windows平台需要编译成.dll的库,打开VS的控制台,进入到对应的build目录下cd build
,如果目录下有文件则需要删除,没有则接下来cmake .. -G "MinGW Makefiles"
, # .为当前目录, “MinGW Makefiles"为makefile类型,如果编译器为vs的话使用"NMake Makefiles”`
如果有其他引用库则需要先cmake ..
完成之后,输入mingw32-make
编译获得最终编译好的.dll文件。
.dll文件复制到C:\Windows\System32
目录下,或者直接在环境变量path
中配置对应的.dll路径目录,涉及到其他库也放在对应目录下。
这样整个部署流程就完毕了。
接下来就是简单的调用:在调用前请关闭idea(所有项目)再重新打开项目,让库重新加载。
java里直接调用对应的方法
public static void main(String[] arg) throws IOException {
System.loadLibrary("libjni");
String NewPkey="1234" ;
sig sig_obj=new sig();
long pkey1=sig_obj.importPkey(NewPkey);
System.out.println(pkey1);
}
如果没有报错,有输出值则说明jni调用成功!