用批处理生成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

已经可以互相调用了,希望可以帮到大家

写批处理是为了同时编译多个文件的本地方法

posted @ 2017-12-26 14:23  BlueBerry006  Views(239)  Comments(0)    收藏  举报