java的数据类型不能直接给c使用,要通过jni转换。
比如String,要通过jni的jstring转换成c语言的char *,其他数据类型也是一样
实践
java层代码
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private static final String TAG = "MainActivity";
private String test = "test";
public native String stringFromJNI();
public native void test();
private double num = 1;
private final double num2 = 2;
public native void doubleFromJNI();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
Log.e(TAG, "onCreate: ");
test();
Log.e(TAG, "onCreate: 修改前 " + num2);
doubleFromJNI();
Log.e(TAG, "onCreate: 修改后 " + num2);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
}
jni
#include
#include
#include
#define TAG "testLog"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
//代码采用C语言编译
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_test(JNIEnv *env, jobject jobject1) {
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_doubleFromJNI(JNIEnv *env, jobject thiz) {
jclass test = env->GetObjectClass(thiz);
// jfieldID num = env->GetFieldID(test, "num", "D");
//
// env->SetDoubleField(thiz,num, 444.5);
jfieldID num2 = env->GetFieldID(test, "num2", "D");
env->SetDoubleField(thiz, num2, 5555.5);
LOGD("SSSSSSSSSSSSSS %d\n", 1312);
}
运行一下看看修改的num2的值
这个是java和jni通信的桥梁。
JNIEnv
看他源码
//当前语言是c++、
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
//当前语言是c语言
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
指的是我们这个文件的后缀
最终
都是访问的这个结构体指针,C语言的
如果方法是静态的就是jclass,否则就是对象实例,
最终jni会打包到apk中成为一个so库
日志库
#include
#define TAG "testLog"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
运行
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private static final String TAG = "MainActivity";
private String test = "test";
public native String stringFromJNI();
public native void test();
private double num = 1;
private double num2 = 2;
public native void doubleFromJNI();
//jni调用它
public int addNum(int a, int b) {
Log.e(TAG, "addNum: ");
return a + b;
}
//
public native void testAddNum();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
Log.e(TAG, "onCreate: ");
test();
Log.e(TAG, "onCreate: 修改前 " + num2);
doubleFromJNI();
Log.e(TAG, "onCreate: 修改后 " + num2);
testAddNum();
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
}
声明一个java函数一个jni函数
在java中调用我们的jni函数
jni中再反调用我们的java函数
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testAddNum(JNIEnv *env, jobject thiz) {
jclass jclass1 = env->GetObjectClass(thiz);
jmethodID add = env->GetMethodID(jclass1, "addNum", "(II)I");
int jint = env->CallIntMethod(thiz, add, 2, 3);
LOGD("============%d\n", jint);
}
输出
字符串函数
jni调用java字符串函数
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_testAddNum(JNIEnv *env, jobject thiz) {
/*jclass jclass1 = env->GetObjectClass(thiz);
jmethodID add = env->GetMethodID(jclass1, "addNum", "(II)I");
int jint = env->CallIntMethod(thiz, add, 2, 3);
LOGD("============%d\n", jint);*/
jclass jclass1 = env->GetObjectClass(thiz);
jmethodID jmethodId = env->GetMethodID(jclass1, "getTestString",
"(Ljava/lang/String;I)Ljava/lang/String;");
jstring va = env->NewStringUTF("22222");
jstring rrr = (jstring) env->CallObjectMethod(thiz, jmethodId, va, 222);
const char *string = env->GetStringUTFChars(rrr,NULL);
LOGD("==============%s\n", string);
}