java jmi的基本思想_jmi: JMI 是 JNI 的 C++11/14封装,目的是为了简化JNI使用
JMI
JNI Modern Interface in C++
特性
支持 Java 方法輸入、輸出參數(shù)
jclass、jmethodID、field 自動(dòng)緩存
C++ 和 Java 方法屬性一致,如靜態(tài)方法對(duì)應(yīng) C++ 靜態(tài)成員函數(shù)
無(wú)需操心局部引用泄漏
getEnv() 支持任意線程,無(wú)需關(guān)心 detach
編譯器推導(dǎo) java 類型及方法簽名,并只生成一次
支持 JNI 原生的各種類型、jmi 的 JObject、C/C++ string 及上述類型的數(shù)組形式(vector, valarray, array等) 作為函數(shù)參數(shù)、返回值及 field 類型
提供了方便使用的常用函數(shù): to_string(std::string), from_string(jstring), android::application()
簡(jiǎn)單易用,用戶代碼極簡(jiǎn)
例子:
JNI_OnLoad 中設(shè)置 java vm: jmi::javaVM(vm);
創(chuàng)建 SurfaceTexture:
// 在任意 jmi::JObject 可見范圍內(nèi)定義 SurfaceTexture tag 類
struct SurfaceTexture : jmi::ClassTag { static std::string name() {return "android/graphics/SurfaceTexture";}};
...
GLuint tex = ...
...
jmi::JObject texture;
if (!texture.create(tex)) {
// texture.error() ...
}
從 SurfaceTexture 構(gòu)造 Surface:
struct Surface : jmi::ClassTag { static std::string name() {return "android.view.Surface";}}; // '.' or '/'
...
jmi::JObject surface;
surface.create(texture);
調(diào)用 void 方法:
texture.call("updateTexImage");
或
texture.call("updateTexImage");
調(diào)用含輸出參數(shù)的方法:
float mat4[16]; // or std::array, valarray
texture.call("getTransformMatrix", std::ref(mat4)); // use std::ref() if parameter should be modified by jni method
若出參類型是 JObject<...> 或器子類, 則可不使用std::ref(),因?yàn)閷?duì)象不會(huì)改變,可能只是某些fields被方法修改了,如
MediaCodec::BufferInfo bi;
bi.create();
codec.dequeueOutputBuffer(bi, timeout); // bi is of type MediaCodec::BufferInfo&
調(diào)用有返回值的方法:
jlong t = texture.call("getTimestamp");
jmethodID 緩存
call/callStatic("methodName", ....) 每次都會(huì)調(diào)用 GetMethodID/GetStaticMethodID(), 而 call/callStatic<...mtag>(...) 只會(huì)調(diào)用一次, 其中 MTag 是 jmi:MethodTag 的子類,實(shí)現(xiàn)了 static const char* name() { return "methodName";}.
// GetMethodID() 對(duì)于每個(gè)不同的方法只會(huì)被調(diào)用一次
struct UpdateTexImage : jmi::MethodTag { static const char* name() {return "updateTexImage";}};
struct GetTimestamp : jmi::MethodTag { static const char* name() {return "getTimestamp";}};
struct GetTransformMatrix : jmi::MethodTag { static const char* name() {return "getTransformMatrix";}};
...
texture.call(); // or texture.call();
jlong t = texture.call();
texture.call(std::ref(mat4)); // use std::ref() if parameter should be modified by jni method
Field 接口
Field 接口支持可緩存和無(wú)緩存 jfieldID
通過(guò) FieldTag 使用可緩存 jfieldID
JObject obj;
...
struct MyIntField : FieldTag { static const char* name() {return "myIntFieldName";} };
auto ifield = obj.field();
jfieldID ifid = ifield; // 或 ifield.id()
ifield.set(1234);
int ivalue = ifield; // 或 ifield.get();
// 靜態(tài) field 也一樣,除了使用的是靜態(tài)方法 JObject::staticField
struct MyStrFieldS : FieldTag { static const char* name() {return "myStaticStrFieldName";} };
auto& ifields = JObject::staticField<:string myintfields>(); // it can be an ref
jfieldID ifids = ifields; // 或 ifield.id()
ifields.set("JMI static field test");
ifields = "assign";
std::string ivalues = ifields; // 或 ifield.get();
通過(guò) field 名字使用無(wú)緩存 jfieldID
auto ifield = obj.field("myIntFieldName");
...
給 Java 類寫個(gè) C++ 類
創(chuàng)建 JObject 或把其對(duì)象作為成員變量,或使用 CRTP JObject。 每個(gè)方法是想通常不超過(guò)3行代碼,也可以使用一些宏使每個(gè)方法實(shí)現(xiàn)只需一行代碼, 參見 JMITest 及 Project AND
使用編譯器生成的簽名
模版 string signature_of(T) 返回類型 T 的簽名. T 可以是 JMI 支持的類型(除了jobject,因?yàn)槠漕愋褪沁\(yùn)行時(shí)確定的)、reference_wrapper、void 及由以上類型作為返回類型和參數(shù)類型的函數(shù)類型
string signature_of(T) 返回的 string 是靜態(tài)存儲(chǔ)的,使用 signature_of(...).data() 是安全的
例子:
void native_test_impl(JNIEnv *env , jobject thiz, ...) {}
staitc const JNINativeMethod gMethods[] = {
{"native_test", signature_of(native_test_impl).data(), native_test_impl},
...
};
也許你發(fā)現(xiàn)了可以用宏來(lái)簡(jiǎn)化
#define DEFINE_METHOD(M) {#M, signature_of(M##_impl).data(), M##_impl}
staitc const JNINativeMethod gMethods[] = {
DEFINE_METHOD(native_test),
...
}
已知問(wèn)題
如果返回類型與前 n 個(gè)參數(shù)類型是一樣的,需要顯示指定這些類型
為什么 JObject 是個(gè)模版?
為了支持 jclass、jmethodID、jfieldID 緩存
已測(cè)編譯器
g++ >= 4.9, clang >= 3.4.2
TODO
modern C++ 類自動(dòng)生成腳本
簽名無(wú)需運(yùn)行時(shí)string
MIT License
Copyright (c) 2016-2019 WangBin
總結(jié)
以上是生活随笔為你收集整理的java jmi的基本思想_jmi: JMI 是 JNI 的 C++11/14封装,目的是为了简化JNI使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql5.7命中率_MySQL5.7
- 下一篇: English trip -- VC(情