JAVA通过JNI调用C语言库
2018-03-20 18:00
176 查看
重点内容##1.前言
- JDK版本1.8.0
- 操作系统 ubuntu 16.04.2
- 目标实现JAVA调用C语言库
java_package_class_nativeapi的格式
( JNIEnv * env,jobject thiz,其他参数)的格式:前两个参数必须存在,需要传递的其他参数可扩展;
JNI类型映射不做过多的描述,只列举几个常用的
如果返回值是jstring类型,需要调用(*env)->NewStringUTF(env,tmpstr)进行转换;
如果希望传递object,那么可以借助jobject thiz这个参数,这里不再详解;
对于nativeapi为init的调用,完全吻合2.3所述
问题原因:libmsauthentjni.so库不在ECLIPSE的标准库路进下;
解决方法:将libmsauthentjni.so的库路径(我的是/usr/local/lib/)加入到环境变量LD_LIBRARY_PATH,然后再其中ECLIPSE程序。
问题原因:jni函数名中的包名或者CLASS和调用的不匹配,详细见本文2.3描述;
解决方法:修改jni函数名中的包名或者CLASS
- JDK版本1.8.0
- 操作系统 ubuntu 16.04.2
- 目标实现JAVA调用C语言库
root@msos:/root# java -version openjdk version "1.8.0_151" OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12) OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
2.JNI层说明
2.1.C语言的JNI封装例程
# define MSAUTHENTJNI_C # include <libmscommon/mscommon.h> # include <libmslog/mslog.h> # include "jni.h" # include "msauthent.h" # define FLAG "msauthentjni" JNIEXPORT void JNICALL Java_jniTest_msauthentjni_init( JNIEnv * env,jobject thiz,jint logopt) { msauthent_oneapi_init(logopt); } JNIEXPORT jint JNICALL Java_jniTest_msauthentjni_getconnect( JNIEnv * env,jobject thiz, jstring product_num,jint debug) { const char* pstr = (*env)->GetStringUTFChars(env,product_num, ms_null); ms_bufcheckret(-1, pstr); int connect=msauthent_oneapi_getconnect(pstr,debug); (*env)->ReleaseStringUTFChars(env,product_num, pstr); return connect; } JNIEXPORT void JNICALL Java_jniTest_msauthentjni_deinit( JNIEnv * env,jobject thiz) { msauthent_oneapi_deinit(); } # undef MSAUTHENTJNI_C
2.2.编译命令
gcc src/msauthentjni.c -DOS_LINUX_X64 -Isrc `pkg-config --cflags libmslog` `pkg-config --cflags libmscommon` `pkg-config --cflags libmstool` `pkg-config --libs libmslog` `pkg-config --libs libmscommon` `pkg-config --libs libmstool` -shared -fPIC -I/usr/lib/jdk/jdk1.8.0_161/include -I/usr/lib/jdk/jdk1.8.0_161/include/linux `pkg-config --libs libmsauthent` `pkg-config --cflags libmsauthent` -o out/lib/libmsauthentjni.so
2.3.格式类型说明
JNI函数固定格式JNIEXPORT 返回值类型 JNICALL java_package_class_nativeapi( JNIEnv * env,jobject thiz,其他参数) ;
java_package_class_nativeapi的格式
“Java_jniTest_msauthentjni_init”中package为jniTest,class为msauthentjni,而nativeapi为init,即这个函数只能被包名为jniTest中的msauthentjni(class)调用,且函数名为init;(类似的还有Java_jniTest_msauthentjni_getconnect,Java_jniTest_msauthentjni_deinit)
( JNIEnv * env,jobject thiz,其他参数)的格式:前两个参数必须存在,需要传递的其他参数可扩展;
JNI类型映射不做过多的描述,只列举几个常用的
Java JNI C/C++ boolean jboolean 8位整型 byte jbyte 带符号的8位整型 char jchar 无符号的16位整型 short jshort 带符号的16位整型 int jint 带符号的32位整型 long jlong 带符号的64位整型 float jfloat 32位浮点型 double jdouble 64位浮点型 String jstring 字符串对象
2.4.特别注意
如果传入的参数是jstring类型,必须要进行转换,转换代码参考函数Java_jniTest_msauthentjni_getconnect中的product_num;如果返回值是jstring类型,需要调用(*env)->NewStringUTF(env,tmpstr)进行转换;
如果希望传递object,那么可以借助jobject thiz这个参数,这里不再详解;
3.JAVA层说明
3.1.JAVA语言调用的JNI例程
package jniTest; public class msauthentjni { static { System.loadLibrary( "msauthentjni" ); } public static native void init( int logopt); public static native int getconnect(String product_num,int debug); public static native void deinit(); public static void main(String[] args) { init(54); System.out.print("------------connect:"+getconnect("MS-EDUECC",1)); deinit(); } }
3.2.说明
库的加载使用System.loadLibrary( “msauthentjni” ),只需要加载最直接的库即可;对于nativeapi为init的调用,完全吻合2.3所述
4. 错误列表
4. 1.环境错误,错误信息如下
`Exception in thread "main" java.lang.UnsatisfiedLinkError: no msauthentjni in java.library.path` at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) `at jniTest.msauthentjni.<clinit>(msauthentjni.java:5)`
问题原因:libmsauthentjni.so库不在ECLIPSE的标准库路进下;
解决方法:将libmsauthentjni.so的库路径(我的是/usr/local/lib/)加入到环境变量LD_LIBRARY_PATH,然后再其中ECLIPSE程序。
`export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH:/usr/local/lib/`
4. 2.JNI函数名错误,错误信息如下
`Exception in thread "main" java.lang.UnsatisfiedLinkError: jniTest.msauthentjni.init(I)V at jniTest.msauthentjni.init(Native Method) at jniTest.msauthentjni.main(msauthentjni.java:15)`
问题原因:jni函数名中的包名或者CLASS和调用的不匹配,详细见本文2.3描述;
解决方法:修改jni函数名中的包名或者CLASS
相关文章推荐
- JAVA通过JNI调用C++程序实践
- 在Android中,通过JNI实现C++与Java相互调用
- JAVA通过JNI调用c++本地方法dll
- 【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(上)
- C通过JNI调用JAVA——创建Object数组参数
- JAVA通过JNI调用本地C语言方法
- Java通过JNI调用CUDA矩阵乘法
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用
- java通过JNI调用C语言写的函数,能提高运行效率吗?
- 使用Qt / C + +通过JNI调用Java代码
- C++ 通过JNI调用Java
- linux下通过JNI用C/C++中调用JAVA类
- java通过jni调用c编译的dll或so
- AndroidJNI 通过C++调用JAVA
- java 通过jni调用dll
- java通过JNI接口调用C语言-初级
- 使用c通过jni调用java
- 通过JNI实现Java和C++的相互调用(转)