学习利用JNI实现Java调C的DLL
来源:互联网 发布:破解软件越来越差 编辑:程序博客网 时间:2024/06/05 10:25
本人最近所做的一个项目需要将C代码移植到Java平台运行。由于先前没有JNI的任何使用经验,花了近一个星期的时间学习,现将过程记录如下。
软件环境:NetBeans IDE 8.0.1 + jdk1.8.0_20 + Visual Studio 2010.
1)首选编写java类JNICode.java:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package test.jnitest;/** * * @author Ai_ViVi */public class JNICode { static{ System.loadLibrary("NativeTestCode"); // 加载dll文件,无需后缀名 } public native void saySomeThing(); public native void passIntArray(int n, int[] a); //传递整型数组 public native ObjTest[] returnIntArray(String[] str); //返回自定义结构数组 /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here //System.out.println(System.getProperty("java.library.path")); System.out.println("hello world from Java"); // for test JNICode obj = new JNICode(); obj.saySomeThing(); int[] a = {1, 2, 3}; obj.passIntArray(3,a); String[] names = {"Dr.1", "Dr.2", "Dr.3", "Dr.4"}; ObjTest[] rObj = obj.returnIntArray(names); for(int i=0; i<rObj.length; i++) { //System.out.println(rObj[i].id); System.out.println(rObj[i].name); } } }
2)测试javah是否可用:
3)利用javah将JNICode.java编译成test_jnitest_JNICode.h文件(注意路径):
test_jnitest_JNICode.h文件位于:
C:\Users\Sandon\Documents\NetBeansProjects\JNItest\build\classes\
/* DO NOT EDIT THIS FILE - it is machine generated */#include "jni.h"/* Header for class test_jnitest_JNICode */#ifndef _Included_test_jnitest_JNICode#define _Included_test_jnitest_JNICode#ifdef __cplusplusextern "C" {#endif/* * Class: test_jnitest_JNICode * Method: saySomeThing * Signature: ()V */JNIEXPORT void JNICALL Java_test_jnitest_JNICode_saySomeThing (JNIEnv *, jobject);/** Class: test_jnitest_JNICode* Method: passIntArray* Signature: (I[I)V*/JNIEXPORT void JNICALL Java_test_jnitest_JNICode_passIntArray(JNIEnv *, jobject, jint, jintArray);/** Class: test_jnitest_JNICode* Method: returnIntArray* Signature: ()[Ltest/jnitest/ObjTest;*/JNIEXPORT jobjectArray JNICALL Java_test_jnitest_JNICode_returnIntArray(JNIEnv *, jobject, jobjectArray);#ifdef __cplusplus}#endif#endif
4)然后创建一个C工程NativeTestCode:
4.1)新建win32项目;
4.2)将C:\ProgramFiles\Java\jdk1.8.0_20\include下jni.h,
C:\ProgramFiles\Java\jdk1.8.0_20\include\win32下的jni_md.h拷贝到工程文件夹下。
4.3)拷贝test_jnitest_JNICode.h到工程文件夹下,并导入工程,打开该文件,将#include <jni.h>修改成#include “jni.h”
4.4)创建test_jnitest_JNICode.cpp文件,成员函数实例化:
#include "stdafx.h"#include "test_jnitest_JNICode.h"JNIEXPORT void JNICALL Java_test_jnitest_JNICode_saySomeThing(JNIEnv *env, jobject jo){printf("hello world from C\n");}JNIEXPORT void JNICALL Java_test_jnitest_JNICode_passIntArray(JNIEnv *env, jobject jo, jint jn, jintArray jarr){int num = jn;jint* aar =env->GetIntArrayElements(jarr,0);int arrLen=env->GetArrayLength(jarr);if (num == arrLen){printf("array length is right\n");}for (int i=0; i<arrLen; i++){printf("%d ", aar[i]);}printf("\n");delete aar;}JNIEXPORT jobjectArray JNICALL Java_test_jnitest_JNICode_returnIntArray(JNIEnv *env, jobject jo, jobjectArray jstr){jclass cls_obj = env->FindClass("test/jnitest/ObjTest"); //获取结构对象jmethodID m = env->GetMethodID(cls_obj,"<init>","()V"); //初始化构造函数 jfieldID fid_id = env->GetFieldID(cls_obj, "id", "I"); //获取成员变量jfieldID fid_name = env->GetFieldID(cls_obj, "name", "Ljava/lang/String;"); //获取成员变量//------------将 char* 转化为 jstring/*char* col_timestamp= "goodluck";//加载string类jclass strClass = env->FindClass("Ljava/lang/String;");//获得方法idjmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");//将字符串转换为jstring jbyteArray bytes_time = env->NewByteArray(strlen(col_timestamp));env->SetByteArrayRegion(bytes_time, 0, strlen(col_timestamp), (jbyte*)col_timestamp);jstring js_time = env->NewStringUTF("utf-8");js_time=(jstring)env->NewObject(strClass, ctorID, bytes_time, js_time); *///------------将 jstring转化为char*int np = env->GetArrayLength(jstr); jclass cls_array=env->FindClass("java/lang/Object"); //创建结构数组jobjectArray obj_array=env->NewObjectArray(np, cls_array, 0); for (int i=0; i< np; i++){jobject obj=env->NewObject(cls_obj,m); int a = i;env->SetIntField(obj, fid_id, a); jobject str = env->GetObjectArrayElement(jstr,i);env->SetObjectField(obj, fid_name, str);env->SetObjectArrayElement(obj_array, i, obj); }return obj_array;}
5)编译NativeTestCode项目生产NativeTestCode.dll文件
6)拷贝NativeTestCode.dll到java\jdk\bin下(假设该路径位于java.library.path下,可以使用System.out.println(System.getProperty("java.library.path"))进行查看),运行JNICode.java文件,结果如下:
另外:
1)如果C工程所生成的dll文件使用了其他dependent libraies(如OpenCV等),则需要将这些dll文件一并放入java.library.path下。
2)如果C工程中使用到了文件读写输入输出等,一定要用绝对路径,否则java调dll会出错。
3)很烦人的一点:一旦C的dll包含隐形错误(能编译通过),java主程序将错误退出,几乎不提供有用的错误信息。
参考:
NetBeans IDE Java快速入门教程:
https://netbeans.org/kb/docs/java/quickstart_zh_CN.html#setup
Java利用JNI调用C/C++写成的DLL(教程):
http://blog.csdn.net/tank_abraham/article/details/32071621
Java向C传入默认类型数组:
http://www.oschina.net/question/214234_162742
java和C之间的数据传递:
http://blog.chinaunix.net/uid-23023613-id-2566756.html
Java向C传递自定义对象的方法:
http://blog.jeoygin.org/2011/12/jni-pass-on-object-parameter.html
Java向C传递对象,中文字符串的方法:
http://lifeixian824.blog.163.com/blog/static/2837428520091222638738/
JNI中参数的传递与操作(分上中下三篇,详细介绍了一些API函数):
http://blog.csdn.net/hudashi/article/details/7058982
C向java返回对象的方法:
http://leidiqiu.iteye.com/blog/720307
- 学习利用JNI实现Java调C的DLL
- JAVA中利用JNI与VS2012实现C/C++的DLL调用
- 利用jni调用c的dll
- JAVA JNI调用C编写的dll
- jni java调用c++实现的dll
- Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能
- 使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能
- Java调用C/C++实现的DLL动态库——JNI
- Java调用C/C++实现的DLL动态库——JNI
- Java学习之通过JNI调用C/C++编写的dll链接库(图文教程)
- Java学习之通过JNI调用C/C++编写的dll链接库(图文教程)
- Android利用JNI实现java调用C或C++
- eclipse JNI示例。利用C/C++实现JAVA中调用的函数
- JNI编程(Java访问C/C++ DLL)的大致步骤
- Java JNI调用dll中的C代码的流程
- java通过jni调用c编译的dll或so
- JNI的学习(Java调用C++函数,通过DLL)
- Java利用JNI调用C/C++的小结
- Android中处理崩溃异常
- Eclipse下配置主题颜色
- 刘博:去担保进程的“量与度”
- C,指向函数的指针,混乱
- Android中使用HTTP服务
- 学习利用JNI实现Java调C的DLL
- Android使用GSP和百度SDK定位
- 机器学习之各种算法(2)
- Java排序算法(九):归并排序
- android framework audiofocus机制
- Let's talk about VMX, which is Intel VT-x's design.
- 更新整理本人所有博文中提供的代码与工具(C++,2014.09)
- Ubuntu14.04 安装问题汇总
- 赫夫曼编码(优先队列实现)