Android NDK 开发入门详解(三) ---- Java和C++方法相互调用

一、Java调用C++方法

NdkTools.java :

package com.suhang.testdemo;

public class NdkTools {

    static {
        System.loadLibrary("native-lib");
    }
    //native 表示该方法为 C++ 方法
    public static native void sayHello();
}
  1. 先使用静态方法load library
  2. 在方法上按Alt+Enter,自动生成 C++ 方法代码
extern "C"
JNIEXPORT void JNICALL
Java_com_suhang_testdemo_NdkTools_sayHello(JNIEnv *env, jclass clazz) {
    // TODO: implement sayHello()
    LOGI("测试代码");
}

方法命名规则:

  1. JNIEXPORT void JNICALL : void 为返回值类型,其余两个为固定写法
  2. Java : 代表是Java方法
  3. com_suhang_testdemo : 包名
  4. NdkTools : 类名
  5. sayHello : 方法名

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		NdkTools.sayHello();
    }
}

执行结果:

2021-10-20 16:12:22.000 12780-12780/com.suhang.testdemo I/suhang: 测试代码

二、C++调用Java方法

2.1 静态方法

2.1.1 C++调用Java静态方法

Ndktools.java

public class NdkTools {
    private static final String TAG = NdkTools.class.getSimpleName();

    static {
        System.loadLibrary("native-lib");
    }

    // C++ 方法,让两个数字相加
    public static native int add(int i1, int i2);

    // Java 方法,在C++方法内部调用该方法。当计算结束后,调用此方法。
    public static int result(int result) {
        Log.d(TAG, "result: " + result);
        return result;
    }
}

native-lib.cpp

extern "C"
JNIEXPORT jint JNICALL
Java_com_suhang_testdemo_NdkTools_add(JNIEnv *env, jclass clazz, jint i1, jint i2) {
    // TODO: implement add()

    // 1. 获取对应类
    //此处传入完整的包名及类型。使用"/"代替"."
    jclass cls = env->FindClass("com/suhang/testdemo/NdkTools");
    // 非空判断
    if (cls == NULL) { return -1; }
    
    // 2. 获取对应方法
    //第一个参数为方法所在类,第二个参数为方法名称,第三个参数为方法签名
    jmethodID method = env->GetStaticMethodID(cls, "result", "(I)I");
    // 非空判断
    if (method == NULL) { return -1; }

    // 3. 调用该方法
    env->CallStaticIntMethod(cls, method, i1 + i2);

    return i1 + i2;
}

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int add = NdkTools.add(2, 3);
        Log.d(TAG, "result is : " + add);
    }
}

调用结果:

2021-10-20 16:37:17.306 13107-13107/com.suhang.testdemo D/NdkTools: result: 5
2021-10-20 16:37:17.307 13107-13107/com.suhang.testdemo D/MainActivity: result is : 5

2.1.2 修改静态变量

与调用静态方法基本一致,只贴部分代码:
native-lib.cpp:

    //获取目标变量
    //第一个参数:类,第二个参数:变量名称,第三个参数:变量类型
    jfieldID fld_name = env->GetStaticFieldID(cls_tools, "name", "Ljava/lang/String;");
    if (fld_name == NULL) {
        return;
    }

    //设置目标变量
    jstring newName = env->NewStringUTF("francis");
    env->SetStaticObjectField(cls_tools, fld_name, newName);

2.2 C++调用实例方法:

调用实例方法与调用静态方法基本无异,只多出两个步骤。

  1. 实现方法类的构造方法
  2. 通过构造方法,实例出方法类

NdkTools.java:

public class NdkTools {
    private static final String TAG = NdkTools.class.getSimpleName();

    static {
        System.loadLibrary("native-lib");
    }
    
    public static native void message();

    public void message(String s){
        Log.d(TAG, "message: "+s);
    }
}

native-lib.cpp

extern "C"
JNIEXPORT void JNICALL
Java_com_suhang_testdemo_NdkTools_message(JNIEnv *env, jclass clazz) {
    // TODO: implement message()

    // 1. 获取对应类
    //此处传入完整的包名及类型。使用"/"代替"."
    jclass cls = env->FindClass("com/suhang/testdemo/NdkTools");
    // 非空判断
    if (cls == NULL) { return; }

    // 2. 获取对应方法
    //第一个参数为方法所在类,第二个参数为方法名称,第三个参数为方法签名
    jmethodID method = env->GetMethodID(cls, "message", "(Ljava/lang/String;)V");
    // 非空判断
    if (method == NULL) { return; }

    //******************************************************************************************
    //******************************************************************************************

    // 3. 找到构造方法
    // C++ 无法直接new出一个类来,所以需要实现一个类的构造方法,用来完成创建类的工作。
    // 构造方法名称为"<init>"
    jmethodID mtd_construct = env->GetMethodID(cls, "<init>", "()V");
    // 非空判断
    if (mtd_construct == NULL) { return; }

    // 4. 实例类
    jobject tools = env->NewObject(cls, mtd_construct, NULL);
    // 非空判断
    if (tools == NULL) {
        return;
    }

    //******************************************************************************************
    //******************************************************************************************

    // 5. 执行方法
    jstring test_message = env->NewStringUTF("测试 message");    //测试数据
    env->CallVoidMethod(tools, method, test_message);

    // 6. 删除引用
    env->DeleteLocalRef(cls);
    env->DeleteLocalRef(tools);
    env->DeleteLocalRef(test_message);
}

执行结果:

2021-10-20 16:57:07.351 13392-13392/com.suhang.testdemo D/NdkTools: message: 测试 message

2.2.2 修改实例变量

与修改静态变量基本一致,不再赘述。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android C 高级编程是指在Android开发中使用C语言进行高级编程的技术。而使用NDK(Native Development Kit)可以使开发者在Android应用中使用C/C++等本地语言进行编程。 NDK是一个工具集,它允许开发者在Android应用中嵌入本地代码,并且提供了一系列的开发工具和库,以便开发者能够在Android应用中使用C/C++进行高级编程。使用NDK可以提供更高的性能和更低的内存占用,适用于需要处理大量数据和高性能计算的应用场景。 在使用NDK进行Android C高级编程时,可以使用PDF(Portable Document Format)作为文档格式,以便对代码和项目进行更好的管理和文档化。在NDK开发过程中,可以使用PDF文档记录关键的设计思路、代码逻辑、接口定义等信息,以方便团队协作和后续的维护。 使用NDK进行Android C高级编程的步骤大致如下: 1. 准备开发环境:安装NDK并配置好开发环境,包括设置NDK的路径和编译器等。 2. 创建新项目:使用Android Studio创建一个新的Android项目,并在项目中引入NDK的支持。 3. 编写C代码:使用C/C++语言编写需要调用的函数、算法或者数据结构等代码,并将其保存在适当的目录下。 4. 编写JNI接口:在生成的Java代码中,使用JNI(Java Native Interface)定义对应C代码的接口,以便在Java调用C代码。 5. 编译和构建:使用NDK的工具集进行编译和构建,将C代码编译成适合Android平台使用的库文件(.so文件)。 6. 在Java代码中调用C代码:在需要调用C代码的地方,使用JNI接口调用对应的C函数,以实现和C代码的交互和调用。 使用PDF文档进行文档化可以帮助开发者更好地组织和管理代码、接口和设计文档等,方便后续的代码维护和项目协作。同时,也可以作为项目的参考文档,方便其他开发人员了解和使用项目。 ### 回答2: Android C 高级编程是针对使用NDK(Native Development Kit)的一种高级编程技术。NDKAndroid开发工具包中的一个工具,允许开发者使用C、C++或其他本地编程语言编写Android应用程序的部分或全部代码。 使用NDK进行Android C高级编程有许多优点。首先,NDK提供了更高的性能和更好的控制权,特别是在处理图形、音频和计算密集型任务时。通过使用本地编程语言,开发者能够更好地利用底层系统资源,提高应用程序的执行效率和速度。 其次,NDK还提供了对现有C和C++库的支持。这意味着开发者可以使用许多已经存在的库和功能来加快开发进程。无需重新编写现有的代码,直接使用NDK与这些库进行集成即可。 在使用NDK进行Android C高级编程时,一种常见的用途是开发游戏。使用C或C++编写游戏代码可以获得更好的性能和更低的延迟,这对于游戏的流畅运行至关重要。 此外,开发者还可以使用NDK为现有的Java应用程序添加本地本地扩展。这样可以通过使用C或C++编写某些关键组件,以改进应用程序的性能或添加新的功能。 总的来说,通过使用NDK进行Android C高级编程,开发者可以获得更高的性能、更好的控制权和更好的资源利用。无论是开发游戏还是优化应用程序,使用NDK都是提高性能和扩展功能的好方法。通过阅读相关的PDF文档,开发者可以更深入地了解如何使用NDK进行Android C高级编程。 ### 回答3: Android NDK (Native Development Kit) 是一个用于开发 Android 应用程序的工具集,它使开发者能够使用 C 或 C++ 编写原生代码,并将其与 Java 编写的 Android 应用程序一起使用。使用 NDK 可以达到增加性能、复用现有的 C/C++ 代码以及访问底层硬件等目的。 在 Android C 高级编程中,使用 NDK 商用 PDF 库可以实现在 Android 应用程序中处理 PDF 文件的功能。PDF 文件是一种常见的电子文档格式,使用 PDF 库可以读取、编辑和生成 PDF 文件。 使用 NDK 进行 PDF 处理的一般步骤如下: 1. 集成 PDF 库:首先,需要将商用的 PDF 库 (.so 文件) 集成到 Android 项目中。可以通过在 Android.mk 文件中添加相关配置,确保 .so 文件正确地被编译和链接到应用程序中。 2. 创建 JNI 接口:为了在 Java 层与 C/C++ 层之间进行通信,需要创建 JNI (Java Native Interface) 接口。可以在创建 JNI 方法时使用 JNAerator 或者手动编写 JNI 代码,以便在 Java调用 C/C++ 的功能。 3. 对 PDF 文件进行处理:在 C/C++ 层,可以使用 PDF 库提供的功能来处理 PDF 文件。例如,可以使用库提供的函数来解析、渲染、添加标注、提取内容等。 4. 将数据返回给 Java 层:在 C/C++ 层处理完之后,可以通过 JNI 接口将处理后的数据返回给 Java 层。这样就可以在 Android 应用程序中显示或者存储处理后的 PDF 文件。 需要注意的是,在使用商用 PDF 库时,需要遵循相关的许可协议,并确保在开发和分发过程中合法使用该库。 总之,通过使用 NDK 和商用 PDF 库,可以使 Android 应用程序具有处理 PDF 文件的高级编程能力。同时,开发者需要具备 C/C++ 编程和 JNI 接口的使用经验,以便顺利地进行开发工作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值