jQuery鼠标指针特效

JNI 基础教学

/*常用引用数据类型对比
 * All object              jobject
 * java.lang.Class         jclass
 * java.lang.String        string
 * int[]                   jintArray
 * Object[]                jobjectArray
 *
 * JNI 函数签名信息
 * java支持函数重载,因此仅仅根据函数名是没法找到对应的JNI函数。
 * 为了解决这个问题,JNI将参数类型和返回值类型作为函数的签名信息
 *
 * JNI规范定义的函数签名信息格式: (参数1类型字符…)返回值类型字符
 *
 * 例子:Java函数 对应的 函数签名
 *  String sayHello2();           "()Ljava/lang/String;"
 *  long fun(int i,Class c)        "(ILjava/lang/Class;)J"
 *  void fun(byte[] bytes)         "([B)V"
 *
 *  JNI常用的数据类型及对应字符:
 *
 *  Java类型        对应字符
 *  void            V
 *  boolean         Z
 *  int             I
 *  long            J
 *  double          D
 *  float           F
 *  byte            B
 *  char            C
 *  short           S
 *  int[]           [i
 *  String          Ljava/lang/String;(后面一定要加;)
 *  Object[]        [Ljava/lang/object;
 *
 *
 *  JNIEnv 是个啥? 它是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数,
 *  用于访问Java成员变量何成员方法,调用Java构造方法创建Java对象等
 *
 *  JNIEnv线程相关性: 每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递
 *
 * */
MainActivity.java
public class MainActivity extends Activity {

    // Used to load the 'myapplication' library on application startup.
    static {
        System.loadLibrary("myapplication");
    }

    private ActivityMainBinding binding;

    private int code = 8;
    private String msg = "hello JNI";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        //java 调用 Native函数
        tv.setText(stringFromJNI());
        tv.setText(sayHello());
        tv.setText(sayHello2());
        tv.setText(sayAloveB(5,2)+"");

        testCallJava(MainActivity.this);
    }

    public void cCallJava(String str){
        Log.i("TAG","cCallJava:" +str);
        Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
    }

    public native void testCallJava(MainActivity activity);

    /**
     * A native method that is implemented by the 'myapplication' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    public native String sayHello();

    public native String sayHello2();

    public native int sayAloveB(int a,int b);
}
native-lib.cpp
#include <jni.h>
#include <string>
#include "android/log.h"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"tww" ,__VA_ARGS__)


extern "C" JNIEXPORT jstring JNICALL
Java_com_autochips_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_autochips_myapplication_MainActivity_sayAloveB(JNIEnv *env, jobject thiz, jint a, jint b) {
    // TODO: implement sayAloveB()
    jint ab = a + b;
    return ab;
}


//静态注册
extern "C"
JNIEXPORT jstring JNICALL
Java_com_autochips_myapplication_MainActivity_sayHello(
        JNIEnv *env, jobject /* this */) {
    std::string hello = "tang say Hello JNI";
    return env->NewStringUTF(hello.c_str());
}

//动态注册
jstring sayHello2(JNIEnv *env, jobject /* this */) {
    std::string hello = "tang sayHello2 ----------";
    //获得一维数组的类引用,即jintArray类型
    jclass intArrayClass = env->FindClass("[I");
    //构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsize
    jobjectArray jobjectArray1 = env->NewObjectArray(6, intArrayClass, NULL);
    return env->NewStringUTF(hello.c_str());
}

static const JNINativeMethod gMethods[] = {
        {"sayHello2",//对应java交互类的名字
         "()Ljava/lang/String;",//对应方法名的函数签名
         (jstring *) sayHello2}//对应 cpp交互类的指针函数
};

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    __android_log_print(ANDROID_LOG_INFO, "native", "Jni_OnLoad");
    JNIEnv *env = NULL;

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK)//从JavaVM获取JNIEnv,一般使用1.4的版本
        return -1;
    //注意:这里 FindClass 必须要和交互类的 包名对应上,并换成[/]符号
    jclass clazz = env->FindClass("com/autochips/myapplication/MainActivity");

    if (!clazz) {
        __android_log_print(ANDROID_LOG_INFO, "native", "cannot get class,"
                                                        "com/autochips/myapplication/MainActivity");
        return -1;
    }

    if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {
        __android_log_print(ANDROID_LOG_INFO, "native", "register native method failed!\n");
        return -1;
    }

    return JNI_VERSION_1_4;
}


//native函数调用Java函数
extern "C"
JNIEXPORT void JNICALL
Java_com_autochips_myapplication_MainActivity_testCallJava(JNIEnv *env, jobject thiz,
                                                           jobject activity) {
    // TODO: implement testCallJava()
    //获取MainActivity
    jclass cls = env->GetObjectClass(activity);
    //拿成员变量ID
    jfieldID codeId = env->GetFieldID(cls,"code","I");
    jfieldID msgId = env->GetFieldID(cls,"msg","Ljava/lang/String;");

    //通过id获取其值
    jint code = env->GetIntField(activity,codeId);
    jstring msg = (jstring)env->GetObjectField(activity,msgId);
    //获取java.lang.String对象中的内容
    const char *cMsg = env->GetStringUTFChars(msg,JNI_FALSE);//C++里面没有

    LOGI("code = %d,msg = %s",code,cMsg);
    env->ReleaseStringUTFChars(msg,cMsg);//用完String之后释放

    //找到函数ID
    jmethodID callJavaMethodId = env->GetMethodID(cls,"cCallJava","(Ljava/lang/String;)V");
    jstring  nativeMsg = env->NewStringUTF("java method cCallJava Go!!!");
    //调用java中的cCallJava函数
    env->CallVoidMethod(activity,callJavaMethodId,nativeMsg);

    // 这里的DeleteLocalRef可以不执行,在函数执行完毕后LocalRef会自动释放,
    // 但是在循环次数较多的循环中需要Delete,否则可能会溢出
    env->DeleteLocalRef(msg);
    env->DeleteLocalRef(nativeMsg);
    env->DeleteLocalRef(cls);
}

JNI 基础
native函数调用Java函数
阿豪JNI

posted @ 2024-03-22 16:48  僵小七  阅读(5)  评论(0编辑  收藏  举报