JNI Modern Interface in C++
to_string(jstring, JNIEnv*)
, from_string(std::string, JNIEnv*)
, android::application()
JNI_OnLoad
中设置 java vm: jmi::javaVM(vm);
创建 SurfaceTexture:
// 在任意 jmi::JObject<SurfaceTexture> 可见范围内定义 SurfaceTexture tag 类
struct SurfaceTexture : jmi::ClassTag { static constexpr auto name() {return JMISTRM("android/graphics/SurfaceTexture");}}; // 或 JMISTR("android.graphics.SurfaceTexture")
...
GLuint tex = ...
...
jmi::JObject<SurfaceTexture> texture;
if (!texture.create(tex)) {
// texture.error() ...
}
struct Surface : jmi::ClassTag { static constexpr auto name() {return JMISTR("android.view.Surface");}}; // '.' or '/'
...
jmi::JObject<Surface> surface;
surface.create(texture);
texture.call("updateTexImage");
或
texture.call<void>("updateTexImage");
float mat4[16]; // or std::array<float, 16>, valarray<float>
texture.call("getTransformMatrix", std::ref(mat4)); // use std::ref() if parameter should be modified by jni method
若出参类型是 JObject<...>
或其子类, 则可不使用std::ref()
,因为对象不会改变,可能只是某些fields被方法修改了,如
MediaCodec::BufferInfo bi;
bi.create();
codec.dequeueOutputBuffer(bi, timeout); // bi is of type MediaCodec::BufferInfo&
auto t = texture.call<jlong>("getTimestamp");
call/callStatic("methodName", ....)
每次都会调用 GetMethodID/GetStaticMethodID()
, 而 call/callStatic<...MTag>(...)
只会调用一次, 其中 MTag
是 jmi:MethodTag
的子类,实现了 static const char* name() { return "methodName";}
.
// GetMethodID() 对于每个不同的方法只会被调用一次
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<UpdateTexImage>(); // or texture.call<void,UpdateTexImage>();
auto t = texture.call<jlong, GetTimestamp>();
texture.call<GetTransformMatrix>(std::ref(mat4)); // use std::ref() if parameter should be modified by jni method
Field 接口支持可缓存和无缓存 jfieldID
通过 FieldTag 使用可缓存 jfieldID
JObject<MyClassTag> obj;
...
struct MyIntField : FieldTag { static const char* name() {return "myIntFieldName";} };
auto ifield = obj.field<jint, MyIntField>();
jfieldID ifid = ifield; // 或 ifield.id()
ifield.set(1234);
jint ivalue = ifield; // 或 ifield.get();
// 静态 field 也一样,除了使用的是静态方法 JObject::staticField
struct MyStrFieldS : FieldTag { static const char* name() {return "myStaticStrFieldName";} };
auto& ifields = JObject<MyClassTag>::staticField<std::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();
通过 field 名字使用无缓存 jfieldID
auto ifield = obj.field<jint>("myIntFieldName");
...
创建 JObject 或把其对象作为成员变量,或使用 CRTP JObject。 每个方法是想通常不超过3行代码,也可以使用一些宏使每个方法实现只需一行代码, 参见 JMITest 及 Project AND
模版 auto signature_of<T>()
返回类型 T 的签名. T 可以是 JMI 支持的类型(除了jobject,因为其类型是运行时确定的)、reference_wrapper、void 及由以上类型作为返回类型和参数类型的函数类型
例子:
void native_test_impl(JNIEnv *env , jobject thiz, ...) {}
staitc const JNINativeMethod gMethods[] = {
{"native_test", signature_of(native_test_impl).data(), native_test_impl},
...
};
也许你发现了可以用宏来简化
#define DEFINE_METHOD(M) {#M, signature_of(M##_impl).data(), M##_impl}
staitc const JNINativeMethod gMethods[] = {
DEFINE_METHOD(native_test),
...
}
需要c++14/17
Copyright (c) 2016-2021 WangBin
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。