使用头文件将C语言中的标准实现通过预编译映射到自己定义的函数中,并在自己定义的函数中调用java函数来实现,这一思路怎么实现呢
首先,通过.h定义函数替换C库中的函数,比如将C中的fopen替换为test_print,新建test.h 文件
// // Created by crow on 2022/6/1. // #ifndef CCDEMO_TEST_H #define CCDEMO_TEST_H #endif //CCDEMO_TEST_H #include#define fopen test_print
新建test.c实现定义的test_print方法,在c里面通过jni调用java代码,要获取JavaVM,然后通过JavaVM获取到当前线程的JNIEnv,代码如下
// // Created by crow on 2022/6/1. // #include "test.h" #include#include JavaVM *javaVm; jstring charToJstring(JNIEnv *env, const char *pat) { jsize len = strlen(pat); jclass strClass = (*env)->FindClass(env, "java/lang/String"); jstring encoding = (*env)->NewStringUTF(env, "utf-8"); jmethodID jmethodId = (*env)->GetMethodID(env, strClass, " ","([BLjava/lang/String;)V"); jbyteArray bytes = (*env)->NewByteArray(env, len); (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) pat); return (jstring) (*env)->NewObject(env, strClass, jmethodId, bytes, encoding); } jstring test_print(const char* filename, const char* mode) { JNIEnv *env = NULL; if ((*javaVm)->AttachCurrentThread(javaVm, &env, NULL) != JNI_OK) { return NULL; } jclass clazz = (*env)->FindClass(env, "com/sun/android/ccdemo/MainActivity"); jobject jobj = (*env)->AllocObject(env, clazz); jmethodID jmethodId = (*env)->GetMethodID(env, clazz, "printLine", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); jstring jFileName = charToJstring(env, filename); jstring jMode = charToJstring(env, mode); return (*env)->CallObjectMethod(env, jobj, jmethodId, jFileName, jMode); } JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { javaVm = vm; JNIEnv *env = NULL; jint result; if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) == JNI_OK) { result = JNI_VERSION_1_6; } else if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) == JNI_OK) { result = JNI_VERSION_1_4; } else { result = JNI_VERSION_1_2; } return result; }
然后通过调用fopen即可实现调用test_print,如在native方法的实现中进行如下调用
在调用native方法的地方进行调用即可如在MainActivity里面进行调用,如下
private void readFile() {
String path = "/storage/emulated/0/document/example2.txt";
Log.e("crow", printFirstLine(path, "r"));
}
public native String printFirstLine(String fileName, String mode);
public String printLine(String fileName, String mode) {
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(fileName, mode);
return randomAccessFile.readLine();
} catch (IOException e) {
return null;
} finally {
try {
if (null != randomAccessFile)
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("crow", "printLine: finally " );
}
}



