java 调用C 函数 通过以下四个案例 1.将传入的两个int 值相加并返回;2.将两个字符串拼接后返回;3.将数组中的每个元素增加10; 4.检查密码是否正确
方法实现
- 编写native方法
package domain.com.rrcc.javacallc;
public class JNI {
{
System.loadLibrary("javacallc");
}
/**
* 让C代码做加法运算,把结果返回
* @param x
* @param y
* @return
*/
public native int add(int x, int y);
/**
* 从java传入字符串,C代码进程拼接
*
* @param s I am from java
* @return I am form java add I am from C
*/
public native String sayHello(String s);
/**
* 让C代码给每个元素都加上10
* @param intArray
* @return
*/
public native int[] increaseArrayEles(int[] intArray);
/*
* 应用: 检查密码是否正确, 如果正确返回200, 否则返回400
*/
public native int checkPwd(String pwd);
}
- 通过javah命令 生成native方法对应的JNI函数声明头文件
javah -d ../jni domain.com.rrcc.javacallc.JNI
生成了jni目录以及下面的domain_com_rrcc_javacallc_JNI.h 头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class domain_com_rrcc_javacallc_JNI */
#ifndef _Included_domain_com_rrcc_javacallc_JNI
#define _Included_domain_com_rrcc_javacallc_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_domain_com_rrcc_javacallc_JNI_add
(JNIEnv *, jobject, jint, jint);
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: sayHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_domain_com_rrcc_javacallc_JNI_sayHello
(JNIEnv *, jobject, jstring);
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: increaseArrayEles
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_domain_com_rrcc_javacallc_JNI_increaseArrayEles
(JNIEnv *, jobject, jintArray);
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: checkPwd
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_domain_com_rrcc_javacallc_JNI_checkPwd
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
- 在步骤2生成的文件夹(jni)下创建并实现对应C/C++文件
javacallc.c 文件
//
// Created by mac on 2019/11/21.
//
/**
* jint:返回值
* Java_全类名_方法名
* JNIEnv *env:
*/
#include "domain_com_rrcc_javacallc_JNI.h"
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
/**
* 把一个jstring转换成一个c语言的char* 类型.
*/
char* _JString2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String");
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr);
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if(alen > 0) {
rtn = (char*)malloc(alen+1); //"\0"
memcpy(rtn, ba, alen);
rtn[alen]=0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba,0);
return rtn;
}
jint JNICALL Java_domain_com_rrcc_javacallc_JNI_add
(JNIEnv* env, jobject jo, jint ji, jint jj){
int result = ji + jj;
return result;
}
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: sayHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
jstring JNICALL Java_domain_com_rrcc_javacallc_JNI_sayHello
(JNIEnv * env, jobject job, jstring jstr){
char* fromJava =_JString2CStr(env,jstr);//I am form java add I am from C
//c:
char* fromC = "add I am from C12";
//拼接函数strcat
strcat(fromJava,fromC);//把拼接的结果放在第一参数里面
//jstring (*NewStringUTF)(JNIEnv*, const char*);
LOGD("fromJava===%s\n",fromJava);
return (*env)->NewStringUTF(env,fromJava);
};
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: increaseArrayEles
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_domain_com_rrcc_javacallc_JNI_increaseArrayEles
(JNIEnv * env, jobject jobj, jintArray jarray){
//1.得到数组的长度
//jsize (*GetArrayLength)(JNIEnv*, jarray);
jsize size = (*env)->GetArrayLength(env,jarray);
//2.得到数组元素
//jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
jint* intArray = (*env)->GetIntArrayElements(env,jarray,JNI_FALSE);
//3.遍历数组,给每个元素加上10
int i;
for(i =0;i<size;i++){
// *(intArray+i) = *(intArray+i) + 10;
*(intArray+i) += 100;
// LOGD("*(intArray+i) === %d\n",*(intArray+i));
}
//4.返回结果
return jarray;
};
/*
* Class: domain_com_rrcc_javacallc_JNI
* Method: checkPwd
* Signature: (Ljava/lang/String;)I
*/
jint JNICALL Java_domain_com_rrcc_javacallc_JNI_checkPwd
(JNIEnv * env, jobject jobj, jstring jstr){
//服务器的密码是123456
char* origin = "123456";
char* fromUser = _JString2CStr(env,jstr);
//函数比较字符串是否相同
int code = strcmp(origin,fromUser);
LOGD("code===%d\n",code);
if(code==0){
return 200;
}else{
return 400;
}
};
- 配置gradle 文件 指定编译的不同CPU
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
defaultConfig {
applicationId "domain.com.rrcc.javacallc"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "libjavacallc" //so文件: lib+moduleName+.so
abiFilters "armeabi-v7a", "x86" //cpu的类型
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// implementation 'com.android.support:appcompat-v7:29.+'
implementation 'com.android.support:appcompat-v7:+'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
- 通过ndk-build 自动生成so文件
在jni目录下创建Android.mk 文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libjavacallc
LOCAL_SRC_FILES := javacallc.c
LOCAL_LDLIBS := -lm -llog
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
003.pngmodule 处右键 选择 Link C++ Project with Gradle
001.png
生成so文件、然后拷贝到app的libs文件目录下
002.png
- 在项目具体调用实现
package domain.com.rrcc.javacallc;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private JNI jni;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
jni = new JNI();
}
public void add(View view){
int result =jni.add(99, 1);
Log.e(MainActivity.class.getSimpleName(),"result==="+result);
}
public void string(View view){
String result =jni.sayHello("I am from java ");
Log.e(MainActivity.class.getSimpleName(), "result===" + result);
}
public void array(View view){
int array[] = {1,2,3,4,5};
int result[] =jni.increaseArrayEles(array);
for(int i=0;i<result.length;i++){
Log.e(MainActivity.class.getSimpleName(),"array["+i+"]==="+array[i]);
}
}
public void checkpw(View view){
int result =jni.checkPwd("123456");
Log.e(MainActivity.class.getSimpleName(), "result===" + result);
}
}
网友评论