C 调用 Java 方法

3 篇文章 0 订阅


在这里插入图片描述

1 Java 代码

JNI 代码

package com.karashok;

import java.util.UUID;

public class JNIDemo {

    /**
     * 获取静态方法返回值
     */
    public static native String sayHello();

    /**
     * 获取方法返回值
     */
    public native String sayWorld();

    /**
     * 修改属性 s
     */
    public native void setS();

    /**
     * 修改静态属性 ss
     * @return
     */
    public native static void setSs();

    private String s = "qwer";
    private static String ss = "asdf";

    public static String getSs() {
        return ss;
    }

    public String getS() {
        return s;
    }

    private long getTime() {
        return System.currentTimeMillis();
    }

    private static String getUUid() {
        return UUID.randomUUID().toString();
    }
}

main 代码

package com.karashok;

public class Main {

    static {
        System.load("libDemo.dylib");
    }
    public static void main(String[] args) {
        JNIDemo demo = new JNIDemo();
        System.out.println("----- 获取静态方法返回值 -----");
        System.out.println("静态方法返回值: " + JNIDemo.sayHello());

        System.out.println("----- 获取方法返回值 -----");
        System.out.println("方法返回值: " + demo.sayWorld());

        System.out.println("----- 修改静态属性 -----");
        System.out.println("静态属性修改前: " + JNIDemo.getSs());
        JNIDemo.setSs();
        System.out.println("静态属性修改后: " + JNIDemo.getSs());

        System.out.println("----- 修改属性 -----");
        System.out.println("属性修改前: " + demo.getS());
        demo.setS();
        System.out.println("属性修改后: " + demo.getS());
    }
}

2 C 代码

需要将 jni.hjni_md.h 两个头文件放到包中。

头文件代码

#include "jni.h"
#include <string.h>

#ifndef DEMO_LIBRARY_H
#define DEMO_LIBRARY_H

/*
 * Class:     com_karashok_JNIDemo
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayHello
(JNIEnv *, jclass);

/*
 * Class:     com_karashok_JNIDemo
 * Method:    sayWorld
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayWorld
(JNIEnv *, jobject);

/*
 * Class:     com_karashok_JNIDemo
 * Method:    setS
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setS
(JNIEnv *, jobject);

/*
 * Class:     com_karashok_JNIDemo
 * Method:    setSs
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setSs
(JNIEnv *, jclass);

#endif //DEMO_LIBRARY_H

代码

#include "library.h"

JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayHello(JNIEnv *jniEnv, jclass jcls) {
    jmethodID mid = (*jniEnv)->GetStaticMethodID(jniEnv,jcls,"getUUid","()Ljava/lang/String;");
    jstring jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv,jcls,mid);
    char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);
    printf("UUID is: %s\n",str);
    return (*jniEnv)->NewStringUTF(jniEnv,"Hello ");
}

JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayWorld(JNIEnv *jniEnv, jobject jobj) {
    jclass jcls = (*jniEnv)->GetObjectClass(jniEnv,jobj);
    jmethodID mid = (*jniEnv)->GetMethodID(jniEnv,jcls,"getTime","()J");
    jlong jl = (*jniEnv)->CallLongMethod(jniEnv,jobj,mid);
    printf("Time is: %ld\n",jl);
    return (*jniEnv)->NewStringUTF(jniEnv,"World!\n");
}

JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setS(JNIEnv *jniEnv, jobject jobj) {
    jclass jcls = (*jniEnv)->GetObjectClass(jniEnv,jobj);
    jfieldID fid = (*jniEnv)->GetFieldID(jniEnv,jcls,"s","Ljava/lang/String;");
    jstring jstr = (*jniEnv)->GetObjectField(jniEnv,jobj,fid);
    char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);
    char newStr[20] = "Demo ";
    strcat(newStr,str);
    jstring newjstr = (*jniEnv)->NewStringUTF(jniEnv,newStr);
    (*jniEnv)->SetObjectField(jniEnv,jobj,fid,newjstr);

}

JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setSs(JNIEnv *jniEnv, jclass jcls) {
    jfieldID fid = (*jniEnv)->GetStaticFieldID(jniEnv,jcls,"ss","Ljava/lang/String;");
    jstring jstr = (*jniEnv)->GetStaticObjectField(jniEnv,jcls,fid);
    char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);
    char newStr[20] = "Demo ";
    strcat(newStr,str);
    jstring newjstr = (*jniEnv)->NewStringUTF(jniEnv,newStr);
    (*jniEnv)->SetStaticObjectField(jniEnv,jcls,fid,newjstr);
}

3 总结

3.1 获取参数
  1. 获取 class 对象
  2. 获取属性的 fieldID
  3. 获取属性值
  4. 将属性值转化为 c 的值
3.2 调用方法
  1. 获取 class 对象
  2. 获取方法的 methodID
  3. 调用方法获取返回值
  4. 将返回值转化为 c 的值

注意: C 调用 Java 方法是不区分权限的,也就是说 public 的属性/方法和 private 的属性/方法是一样的。

获取方法签名:javap -s -p com.karashok.JNIDemo,一定要尽到相应 src 的根目录下而不是类的目录。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值