赞
踩
在Kotlin和C++之间通过JNI进行接口传递时,需要注意两边参数定义的映射关系。JNI(Java Native Interface)为Java(Kotlin也适用)与本地语言(如C/C++)之间的交互提供了桥梁。在Kotlin中定义的外部函数和C++中的实现需要通过JNI签名相互对应。
在Kotlin中,我们定义一个包含external
方法的类。例如:
package com.example.native
class NativeLib {
external fun stringFromJNI(): String
external fun addNumbers(a: Int, b: Int): Int
companion object {
init {
System.loadLibrary("native-lib")
}
}
}
在C++中,我们需要定义与Kotlin中external
方法对应的函数实现,并使用正确的JNI签名。每个参数类型在JNI中都有对应的类型签名。
Kotlin类型 | JNI签名 | C++类型 |
---|---|---|
Int | I | jint |
Long | J | jlong |
Boolean | Z | jboolean |
Byte | B | jbyte |
Char | C | jchar |
Short | S | jshort |
Float | F | jfloat |
Double | D | jdouble |
String | Ljava/lang/String; | jstring |
Array | [ | jarray |
Object | L…; | jobject |
stringFromJNI
和addNumbers
生成JNI头文件:
假设已经生成了Kotlin类对应的.class文件,可以使用javac
生成头文件:
javac -h . path/to/classes/com/example/native/NativeLib.class
生成的头文件com_example_native_NativeLib.h
可能如下所示:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_native_NativeLib */ #ifndef _Included_com_example_native_NativeLib #define _Included_com_example_native_NativeLib #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_native_NativeLib * Method: stringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_native_NativeLib_stringFromJNI (JNIEnv *, jobject); /* * Class: com_example_native_NativeLib * Method: addNumbers * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_native_NativeLib_addNumbers (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
实现C++方法:
创建对应的C++文件native-lib.cpp
,并实现这些方法:
#include <jni.h>
#include <string>
#include "com_example_native_NativeLib.h"
JNIEXPORT jstring JNICALL Java_com_example_native_NativeLib_stringFromJNI(JNIEnv *env, jobject obj) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
JNIEXPORT jint JNICALL Java_com_example_native_NativeLib_addNumbers(JNIEnv *env, jobject obj, jint a, jint b) {
return a + b;
}
加载本地库:
在Kotlin中,加载本地库并调用本地方法:
package com.example.main
import com.example.native.NativeLib
fun main() {
val nativeLib = NativeLib()
val resultString = nativeLib.stringFromJNI()
val sum = nativeLib.addNumbers(3, 5)
println(resultString) // 输出: Hello from C++
println(sum) // 输出: 8
}
确保本地库存在:
确保native-lib
库文件存在并可以在运行时加载。通常在Android项目中,会把.so文件放在src/main/jniLibs/
目录下。
JNIEnv
指针和jobject
对象是每个本地方法的必需参数。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。