SDK_APP/JNI_FIX_SUMMARY.md

142 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<SensorData>?
}
```
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<SensorData>?
```
#### 优势
- 保持原有的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. 享受重构后的代码结构优势