JNI - 如何使用多个JNI包装实例与不同的领域? [英] JNI - how to use multiple Jni wrapper instances with different fields?

查看:198
本文介绍了JNI - 如何使用多个JNI包装实例与不同的领域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我有一个使用JNI(NDK使用),以code在Java和C / C ++。

的Andr​​oid项目

我创建在Java端JNI的Java包装,将自行完成所有的JNIØprerations,而没有其他的Java类可以访问超过这个包装。

其他直接的JNI操作

问题

问题是,我想创建该包装的多个实例,而JNI的部分应该有每JNI包装一个实例。

这是一个问题,因为JNI部分适用于所有情况下相同的字段。

问题

如何才能解决这个问题,这样对于JNI包装的每一个Java实例,将有上JNI部分的实例?

我在想,也许我可以把所有的场为C ++类,并有一个init()函数将返回它的一个新实例为JniWrapper的CTOR,从此,每个JNI函数需要的字段,它会得到这个类作为一个参数。也许它可能是一个指针在此链接如图所示。

不幸的是,我不知道该怎么做。

任何人都可以请帮助?

样品

下面是一个示例code,我希望将这些东西更清楚谁不明白的问题:

Java的一部分:

 公共类JniWrapper
  {
  静态的
    {
    的System.loadLibrary(JniTest);
    }  私人本地无效美孚(位图位图);
  }

JNI部分:

  ...
//可悲的是,所有这些领域实际上是一个全球性的领域
INT _intField;
浮_floatField;
//那些只是样品领域。我也想存储指针和对象...JNIEXPORT无效JNICALL ...美孚(JNIEnv的* ENV,jobject OBJ,jobject位图)
  {
  //做一些与领域,因为如果他们都属于JniWrapper,
  //和JniWrapper的其他实例被允许改变他们
  }


解决方案

我已经找到了一个可能的解决方案(链接的这里),要么使用jlong​​或jobject是一个句柄(或指针,如果你想)到已在JNI侧创建的对象。

人说,这是更好地使用jobject为ByteBuffer的,而不是为jlong​​更好的兼容性的。

的解决方案是:

Java方面:

 私人原生的ByteBuffer的init();
私人本地无效美孚(ByteBuffer的手柄);

JNI端:

  / **类来保存的字段* /
类FieldsHolder
  {
  ... //私人领域,为每个实例
  }

创建JNI对象和发送到Java方面:

  JNIEXPORT jobject JNICALL ...的init(JNIEnv的* ENV,jobject OBJ)
  {
  FieldsHolder * MyClass的=新FieldsHolder();
  之类的... // prepare领域
  返回env-> NewDirectByteBuffer(MyClass的,0);
  }

重新使用JNI对象:

  JNIEXPORT无效JNICALL ...美孚(JNIEnv的* ENV,jobject OBJ,jobject手柄)
  {
  FieldsHolder * MyClass的=(FieldsHolder *)env-> GetDirectBufferAddress(句柄);
  //现在我们可以再次访问该领域。
  }

background

I have an android project that uses JNI (using NDK) to code in both Java and C/C++.

I've created a Jni java wrapper on the java side that will do all the Jni oprerations by itself, while no other java class can access the jni operations directly other than this wrapper.

the problem

problem is , i wish to create multiple instances of this wrapper, while the Jni part should have an instance per Jni wrapper.

this is a problem, since the Jni part holds the same fields for all instances.

the question

How can i solve this problem, so that for each java instance of the jni wrapper, there will be an instance on the jni part?

I was thinking, maybe I could put all of the fields into a C++ class, and have an init() function that will return a new instance of it for the CTOR of the JniWrapper, and from then, for each JNI function that needs fields, it will get this class as a parameter . maybe it could be a pointer as shown on this link.

sadly, i have no idea how to do it.

can anyone please help?

sample

here's a sample code that I hope will make things clearer for those who didn't understand the problem:

java part:

public class JniWrapper
  {
  static
    {
    System.loadLibrary("JniTest");
    }

  private native void foo(Bitmap bitmap);
  }

jni part:

...
// sadly, all of those fields are actually a global fields
int _intField;
float _floatField;    
//those are just sample fields. i would also like to store pointers and objects...

JNIEXPORT void JNICALL ...foo(JNIEnv * env, jobject obj, jobject bitmap)
  {
  // do something with the fields, as if they all belong to the JniWrapper, 
  // and no other instances of JniWrapper are allowed to change them
  }

解决方案

I've found a possible solution (link here), to either use a jlong or jobject to be a handle (or pointer, if you wish) to the object that was created on the JNI side.

people said it's better to use a jobject as ByteBuffer instead of jlong for better compatibility.

the solution is :

Java side:

private native ByteBuffer init();
private native void foo(ByteBuffer handle);

JNI side:

/**a class to hold the fields*/
class FieldsHolder
  {
  ... //private fields, for each instance
  }

creating the JNI object and sending to java side:

JNIEXPORT jobject JNICALL ...init(JNIEnv * env, jobject obj)
  {
  FieldsHolder* myClass= new FieldsHolder();
  ... //prepare fields of the class
  return env->NewDirectByteBuffer(myClass, 0);
  }

re-using the JNI object :

JNIEXPORT void JNICALL ...foo(JNIEnv * env, jobject obj, jobject handle)
  {
  FieldsHolder* myClass= (FieldsHolder*) env->GetDirectBufferAddress(handle);
  //now we can access the fields again.
  }

这篇关于JNI - 如何使用多个JNI包装实例与不同的领域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆