SDK_APP/JNI_FIX_SUMMARY.md

4.0 KiB
Raw Blame History

JNI函数名不匹配问题修复说明

问题描述

在代码重构过程中,将原生方法从MainActivity移动到DataManager类后,出现了以下错误:

Cannot resolve corresponding JNI function Java_com_example_cmake_1project_1test_DataManager_createStreamParser

问题原因

JNI函数命名规则

JNI函数名遵循以下格式

Java_{包名}_{类名}_{方法名}

其中:

  • 包名中的点(.)用下划线(_)替换
  • 类名中的下划线用_1替换

具体变化

重构前的JNI函数名在MainActivity中

Java_com_example_cmake_1project_1test_MainActivity_createStreamParser
Java_com_example_cmake_1project_1test_MainActivity_destroyStreamParser
Java_com_example_cmake_1project_1test_MainActivity_streamParserAppend
Java_com_example_cmake_1project_1test_MainActivity_streamParserDrainPackets

重构后的JNI函数名在DataManager中

Java_com_example_cmake_1project_1test_DataManager_createStreamParser
Java_com_example_cmake_1project_1test_DataManager_destroyStreamParser
Java_com_example_cmake_1project_1test_DataManager_streamParserAppend
Java_com_example_cmake_1project_1test_DataManager_streamParserDrainPackets

解决方案

方案1回调接口模式已实现

通过创建回调接口,让DataManager通过MainActivity来调用原生方法保持原有的JNI函数名。

实现步骤

  1. 创建回调接口
interface NativeMethodCallback {
    fun createStreamParser(): Long
    fun destroyStreamParser(handle: Long)
    fun streamParserAppend(handle: Long, chunk: ByteArray)
    fun streamParserDrainPackets(handle: Long): List<SensorData>?
}
  1. 修改DataManager构造函数
class DataManager(private val nativeCallback: NativeMethodCallback)
  1. MainActivity实现接口
class MainActivity : AppCompatActivity(), DataManager.NativeMethodCallback
  1. 保持原生方法在MainActivity中
// 原生方法声明 - 保持原来的JNI函数名
external fun createStreamParser(): Long
external fun destroyStreamParser(handle: Long)
external fun streamParserAppend(handle: Long, chunk: ByteArray)
external fun streamParserDrainPackets(handle: Long): List<SensorData>?

优势

  • 保持原有的JNI函数名无需修改C++代码
  • 维持了代码重构的架构优势
  • 清晰的职责分离

劣势

  • 增加了接口依赖
  • 稍微增加了代码复杂度

方案2修改C++代码中的JNI函数名

如果您有权限修改C++代码可以将C++中的JNI函数名改为新的名称。

需要修改的C++函数名

// 原来的函数名
JNIEXPORT jlong JNICALL Java_com_example_cmake_1project_1test_MainActivity_createStreamParser

// 改为
JNIEXPORT jlong JNICALL Java_com_example_cmake_1project_1test_DataManager_createStreamParser

优势

  • 完全符合重构后的架构
  • 无需额外的接口层

劣势

  • 需要修改C++代码
  • 可能影响其他依赖项目

推荐方案

推荐使用方案1回调接口模式,原因如下:

  1. 无需修改C++代码保持现有C++代码的稳定性
  2. 维持重构优势:仍然保持了代码的职责分离
  3. 向后兼容如果将来需要可以轻松切换到方案2
  4. 风险较低:不会引入新的编译或链接问题

修复后的架构

MainActivity (实现NativeMethodCallback)
    ↓
DataManager (通过回调调用原生方法)
    ↓
原生C++库 (保持原有JNI函数名)

注意事项

  1. JNI函数名一致性确保Kotlin中的external方法名与C++中的JNI函数名完全匹配
  2. 库加载:确保在MainActivitycompanion object中正确加载原生库
  3. 接口实现MainActivity必须实现NativeMethodCallback接口的所有方法
  4. 依赖注入DataManager的构造函数现在需要传入回调接口实例

验证修复

修复完成后,您应该能够:

  1. 成功编译项目
  2. 不再看到JNI函数名不匹配的错误
  3. 保持原有的功能正常运行
  4. 享受重构后的代码结构优势