用批处理生成jni动态库java和c之间互相调用
windows环境搭建
java环境就不多说了,主要是c环境,根据自己的windows系统下载32或64位的。这里用的是mingw64下载地址 https://sourceforge.net/projects/mingw-w64/files/latest/download
安装之后配置path环境变量 d:\mingw64\bin这里换成自己的mingw64安装路径
首先说生成动态库的方法
生成头文件批处理代码:替别提示:.bat文件最好用ansi编码方式保存
GenerateHeadFile.bat
set dirpath=%cd%
setlocal enabledelayedexpansion
rem改成你自己的包名
set packageName=smart.cn.
rem包名路径
set packagePath=smart\cn\
rem循环生成java文件夹下的java本地方法头文件,注意此文件夹下java文件是带包名的,比如smrt\cn\就是把smart文件夹直接拷贝到java文件夹下
for %%c in (%dirpath%\java\%packagePath%*.java) do javah -jni -classpath %dirpath%\java -d %dirpath%\c %packageName%%%~nc
生成dll动态库批处理代码
GenerateDll.bat
set dirpath=%cd% setlocal enabledelayedexpansion rem你自己想生成的dll库文件名 set dllName=JniMethod.dll rem循环编译c文件夹里的c文件 for %%c in (%dirpath%\c\*.c) do gcc -c -I"D:\Program Files\Java\jdk1.8.0_131\include" -I"D:\Program Files\Java\jdk1.8.0_131\include\win32" %dirpath%\c\%%~nc.c -o o\%%~nc.o rem将o文件夹里编译好的c程序生成dll动态库 gcc -Wl,--add-stdcall-alias -shared -o dll/%dllName% %dirpath%\o\*.o
新建一个文件夹随便起名然后在里面分别创建c,dll,java,o文件夹。在创建一个.bat文件,这个名字也是随便起

点击GenerateHeadFile.bat在c文件夹下生成头文件smart_cn_JniMethod.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class smart_cn_JniMethod */ #ifndef _Included_smart_cn_JniMethod #define _Included_smart_cn_JniMethod #ifdef __cplusplus extern "C" { #endif /* * Class: smart_cn_JniMethod * Method: getData * Signature: (II)[[I */ JNIEXPORT jobjectArray JNICALL Java_smart_cn_JniMethod_getData (JNIEnv *, jobject, jint, jint); /* * Class: smart_cn_JniMethod * Method: getArray * Signature: (I)[I */ JNIEXPORT jintArray JNICALL Java_smart_cn_JniMethod_getArray (JNIEnv *, jclass, jint); /* * Class: smart_cn_JniMethod * Method: callJava1 * Signature: ()V */ JNIEXPORT void JNICALL Java_smart_cn_JniMethod_callJava1 (JNIEnv *, jobject); /* * Class: smart_cn_JniMethod * Method: callJava2 * Signature: ()V */ JNIEXPORT void JNICALL Java_smart_cn_JniMethod_callJava2 (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
实现里面的c方法smart_cn_JniMethod.c
#include <stdio.h> #include "smart_cn_JniMethod.h" /* * Class: JniMethod * Method: getData * Signature: (II)[[I */ JNIEXPORT jobjectArray JNICALL Java_smart_cn_JniMethod_getData (JNIEnv *env, jobject obj, jint x, jint y){
//获取一个数组对象类型 jclass jarrayClass=(*env)->FindClass(env,"[I");
//创建一个数组对象 jobjectArray jobjectArr=(*env)->NewObjectArray(env,x,jarrayClass,NULL); for(int i=0;i<y;i++){
//创建一个int类型的数组 jintArray jintArr=(*env)->NewIntArray(env,y); jint temp[y]; for(int j;j<y;j++){ temp[j]=i+j; }
//将c中temp数组设置给jintarray (*env)->SetIntArrayRegion(env,jintArr,0,y,temp);
//将数组放到数组对象里面 (*env)->SetObjectArrayElement(env,jobjectArr,i,jintArr);
//回收jintarray局部变量 (*env)->DeleteLocalRef(env,jintArr); } return jobjectArr; } /* * Class: JniMethod * Method: getArray * Signature: (I)[I */ JNIEXPORT jintArray JNICALL Java_smart_cn_JniMethod_getArray (JNIEnv *env, jclass jcs, jint x){ jint temp[x]; for(int i=0;i<x;i++){ temp[i]=i; } jintArray jarr=(*env)->NewIntArray(env,x); (*env)->SetIntArrayRegion(env,jarr,0,x,temp); return jarr; } /* * Class: JniMethod * Method: callJava1 * Signature: ()V */ JNIEXPORT void JNICALL Java_smart_cn_JniMethod_callJava1 (JNIEnv *env, jobject obj){ jclass clazz=(*env)->FindClass(env,"Lsmart/cn/JniMethod;"); if (clazz == NULL) { printf("Not find JniMethod class"); return; } jmethodID mid_construct=(*env)->GetMethodID(env,clazz,"<init>","()V"); if (mid_construct == NULL) { printf("Not found defult construction"); return; } jmethodID jm=(*env)->GetMethodID(env,clazz,"jniToJava","(Ljava/lang/String;)V"); if (jm == NULL) { printf("Not found jniToJava() method"); return; } jobject jobj=(*env)->NewObject(env,clazz,mid_construct); jstring s=(*env)->NewStringUTF(env, "Hello java_Java_JniMethod_callJava1"); (*env)->CallVoidMethod(env,jobj,jm,s); (*env)->DeleteLocalRef(env,jobj); (*env)->DeleteLocalRef(env,obj); } /* * Class: JniMethod * Method: callJava2 * Signature: ()V */ JNIEXPORT void JNICALL Java_smart_cn_JniMethod_callJava2 (JNIEnv *env, jclass jcs){ jclass clazz=(*env)->FindClass(env,"Lsmart/cn/JniMethod;"); if (clazz == NULL) { printf("Not find JniMethod class"); return; } jmethodID jm=(*env)->GetMethodID(env,clazz,"jniToJava","(Ljava/lang/String;)V"); if (jm == NULL) { printf("Not found jniToJava() method"); return; } jstring s=(*env)->NewStringUTF(env, "Hello java_Java_JniMethod_callJava2"); (*env)->CallStaticVoidMethod(env,clazz,jm,s); (*env)->DeleteLocalRef(env,jcs); }
这时候就可以点击GenerateDll.bat在o文件夹下生成编译后的.o文件,在dll文件夹下生成JniMethod.dll
JniMethod.java文件的代码
package smart.cn; public class JniMethod{ public native int[][] getData(int x,int y); public native static int[] getArray(int x); public native void callJava1(); public native static void callJava2(); public void jniToJava(String str) { System.out.println("jni to java:"+str); } }
在编写一个TestJni.java可以使用刚才编好的dll动态库
package smart.cn; public class TestJni{ static { // hello.dll (Windows) or libhello.so (Unixes) System.loadLibrary("jni/JniMethod"); } public static void main(String args[]){ int [][]data=new JniMethod().getData(2,2); for(int arr[]:data){ for(int i:arr){ System.out.println(i); } } int []arr=JniMethod.getArray(3); for(int i:arr){ System.out.println("_"+i); } new JniMethod().callJava1(); JniMethod.callJava2(); } }
新建一个Test文件夹把带包名的java文件拷贝过来,在Test文件夹里面在新建一个jni文件夹把刚才生成dll动态库拷贝进去
在dos命令好运行

代码原文件地址:https://files.cnblogs.com/files/blueberry006/jni.zip
已经可以互相调用了,希望可以帮到大家
写批处理是为了同时编译多个文件的本地方法

浙公网安备 33010602011771号