# 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. **创建回调接口** ```kotlin interface NativeMethodCallback { fun createStreamParser(): Long fun destroyStreamParser(handle: Long) fun streamParserAppend(handle: Long, chunk: ByteArray) fun streamParserDrainPackets(handle: Long): List? } ``` 2. **修改DataManager构造函数** ```kotlin class DataManager(private val nativeCallback: NativeMethodCallback) ``` 3. **MainActivity实现接口** ```kotlin class MainActivity : AppCompatActivity(), DataManager.NativeMethodCallback ``` 4. **保持原生方法在MainActivity中** ```kotlin // 原生方法声明 - 保持原来的JNI函数名 external fun createStreamParser(): Long external fun destroyStreamParser(handle: Long) external fun streamParserAppend(handle: Long, chunk: ByteArray) external fun streamParserDrainPackets(handle: Long): List? ``` #### 优势 - 保持原有的JNI函数名,无需修改C++代码 - 维持了代码重构的架构优势 - 清晰的职责分离 #### 劣势 - 增加了接口依赖 - 稍微增加了代码复杂度 ### 方案2:修改C++代码中的JNI函数名 如果您有权限修改C++代码,可以将C++中的JNI函数名改为新的名称。 #### 需要修改的C++函数名 ```cpp // 原来的函数名 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. **库加载**:确保在`MainActivity`的`companion object`中正确加载原生库 3. **接口实现**:MainActivity必须实现`NativeMethodCallback`接口的所有方法 4. **依赖注入**:DataManager的构造函数现在需要传入回调接口实例 ## 验证修复 修复完成后,您应该能够: 1. 成功编译项目 2. 不再看到JNI函数名不匹配的错误 3. 保持原有的功能正常运行 4. 享受重构后的代码结构优势