C ++代码学习笔记(一)

1、GetStringUTFChars

用于将 Java 字符串(jstring)转换为 UTF-8 编码的 C 风格字符串(const char*)。

必须 在使用完后调用 ReleaseStringUTFChars 释放内存,否则可能导致内存泄漏。

cpp 复制代码
std::string data_converter::convertJavaStringToCpp(JNIEnv* env, jstring jStr) {
    const char* cStr = env->GetStringUTFChars(jStr, nullptr);
    std::string result(cStr);
    env->ReleaseStringUTFChars(jStr, cStr);
    return result;
}

2、NewStringUTF

用于将 C/C++ 的 UTF-8 字符串 转换为 Java 的 jstring 对象。

cpp 复制代码
const char *cStr = "Hello from C++! 你好!";
jstring javaStr = env->NewStringUTF(cStr);

3、GetArrayLength

用于获取 Java 数组的长度。

cpp 复制代码
JNIEXPORT jint JNICALL Java_Example_getArrayLength(JNIEnv *env, jobject obj, jintArray arr) {
    jsize length = env->GetArrayLength(arr);
    return length;
}

4、GetObjectArrayElement

用于从 Java 对象数组中获取指定索引处的元素。

对于基本类型数组(如 int[], float[] 等),不能直接使用 GetObjectArrayElement,而应该使用对应的函数如 GetIntArrayElements。

cpp 复制代码
JNIEXPORT void JNICALL Java_Example_printArrayElements(JNIEnv *env, jobject obj, jobjectArray arr) {
    jsize length = env->GetArrayLength(arr);
    for (jsize i = 0; i < length; i++) {
        jobject element = env->GetObjectArrayElement(arr, i);
        // 对 element 进行操作...
    }
}

5、GetByteArrayRegion

用于将 Java 字节数组 (jbyteArray) 的一部分或全部复制到 C/C++ 的本地缓冲区中。

cpp 复制代码
JNIEXPORT void JNICALL Java_Example_processByteArray(
    JNIEnv *env, 
    jobject obj, 
    jbyteArray javaArray) 
{
    // 获取数组长度
    jsize length = env->GetArrayLength(javaArray);
    
    // 分配本地缓冲区
    jbyte *buffer = new jbyte[length];
    
    // 复制整个数组到本地缓冲区
    env->GetByteArrayRegion(javaArray, 0, length, buffer);
    
    // 处理数据...
    for (jsize i = 0; i < length; i++) {
        // 处理 buffer[i]...
    }
    
    // 释放本地缓冲区
    delete[] buffer;
}

6、(void)env;(void)instance;

这两行是用于 显式忽略未使用参数 的编程技巧。

cpp 复制代码
static void saveDeviceID(JNIEnv* env, jobject instance, jstring devID)
{
    (void)env;      // 明确表示不使用 env 参数
    (void)instance; // 明确表示不使用 instance 参数
    // ...
}

7、GetObjectClass

用于在 C/C++ 代码中获取 Java 对象的类引用。它通常在编写本地方法(native methods)时使用。

cpp 复制代码
#include <jni.h>

JNIEXPORT void JNICALL Java_Example_printClassName(JNIEnv *env, jobject obj) {
    // 获取传入对象的类
    jclass cls = env->GetObjectClass(obj);
    
    // 获取类名
    jmethodID mid_getName = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
    jstring name = (jstring)env->CallObjectMethod(cls, mid_getName);
    
    const char *str = env->GetStringUTFChars(name, NULL);
    printf("Class name: %s\n", str);
    env->ReleaseStringUTFChars(name, str);
}

替代方案

如果你想获取某个已知类的引用(而不是通过对象实例),可以使用 FindClass() 函数:

cpp 复制代码
jclass cls = env->FindClass("java/lang/String");

GetObjectClass() 主要用于当你已经有一个对象实例但需要访问其类信息时使用。

8、NewGlobalRef

用于创建一个全局引用(global reference)到 Java 对象。全局引用在本地代码中跨多个本地方法调用时保持有效,直到显式释放。

cpp 复制代码
// 全局变量存储引用
jclass globalClassRef;

JNIEXPORT void JNICALL Java_Example_init(JNIEnv *env, jobject obj) {
    // 获取局部引用
    jclass localClassRef = env->GetObjectClass(obj);
    
    // 创建全局引用
    globalClassRef = (jclass)env->NewGlobalRef(localClassRef);
    
    // 局部引用不再需要时可以删除
    env->DeleteLocalRef(localClassRef);
}

JNIEXPORT void JNICALL Java_Example_cleanup(JNIEnv *env, jobject obj) {
    // 不再需要时释放全局引用
    if (globalClassRef != NULL) {
        env->DeleteGlobalRef(globalClassRef);
        globalClassRef = NULL;
    }
}

相关函数

  • DeleteGlobalRef(): 释放全局引用

  • NewLocalRef(): 创建局部引用

  • NewWeakGlobalRef(): 创建弱全局引用

9、

cpp 复制代码
    NetworkManagerCallback() = default;
    virtual ~NetworkManagerCallback() = default;
    NetworkManagerCallback(const NetworkManagerCallback& other) = delete;
    NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;

这几行代码展示了一个类中常见的特殊成员函数的声明和定义方式。

  1. NetworkManagerCallback() = default;

    • 使用编译器生成的默认构造函数

    • 示例:当创建NetworkManagerCallback对象时,会调用这个默认构造函数

    cpp 复制代码
    NetworkManagerCallback callback; // 使用默认构造函数
  2. virtual ~NetworkManagerCallback() = default;

    • 声明虚析构函数并使用默认实现

    • 使得这个类可以作为基类被继承,且能正确调用派生类的析构函数

    • 示例:

    cpp 复制代码
    class DerivedCallback : public NetworkManagerCallback {
        ~DerivedCallback() override { /* 清理资源 */ }
    };
  3. NetworkManagerCallback(const NetworkManagerCallback& other) = delete;

    • 禁用拷贝构造函数

    • 示例:以下代码会编译错误

    cpp 复制代码
    NetworkManagerCallback cb1;
    NetworkManagerCallback cb2(cb1); // 错误:拷贝构造函数被删除
  4. NetworkManagerCallback& operator=(const NetworkManagerCallback& other) = delete;

    • 禁用拷贝赋值运算符

    • 示例:以下代码会编译错误

    cpp 复制代码
    NetworkManagerCallback cb1;
    NetworkManagerCallback cb2;
    cb2 = cb1; // 错误:拷贝赋值运算符被删除

这种模式通常用于:

  • 需要作为基类但不需要拷贝功能的类(如回调接口)

  • 只允许移动不允许拷贝的类

  • 单例模式实现

相关推荐
A9better16 小时前
嵌入式开发学习日志31——stm32之外部中断与定时器中断的差别与选择
stm32·单片机·学习
zhangrelay16 小时前
ROS2学习研究版本推荐:Jazzy Jalisco(LTS长期支持版)AI版本251001
笔记·学习
xyx-3v18 小时前
已知三极管的类型(NPN/PNP)和基极引脚,如何区分集电极(c)和发射极(e)
单片机·嵌入式硬件·学习
大白的编程日记.18 小时前
【Linux学习笔记】线程概念和控制(二)
linux·笔记·学习
半夏知半秋18 小时前
skynet-socket.lua源码分析
服务器·开发语言·学习·架构·lua
低代码布道师18 小时前
学习低代码,需要什么基础?
学习·低代码
克里斯蒂亚诺更新19 小时前
OpenSSL 3.0对某些加密算法增加了限制
笔记
2401_8414956419 小时前
【数据结构】红黑树的基本操作
java·数据结构·c++·python·算法·红黑树·二叉搜索树
西猫雷婶19 小时前
random.shuffle()函数随机打乱数据
开发语言·pytorch·python·学习·算法·线性回归·numpy
随机惯性粒子群19 小时前
STM32控制开发学习笔记【基于STM32 HAL库】
笔记·stm32·嵌入式硬件·学习