JNI编程

时间:2017-09-04 11:07:06

标签: java android java-native-interface jnienv

我是jni编程的新手。我想将一个float数组从java传递给jni,动态分配足够的内存到jni端的float数组,在jfloatArray中存储一些值,并在java中访问它。我不想返回jfloatArray,只需修改传递的输入float数组。我尝试了下面的方法,但它没有修改我的java float数组。怎么做到这一点?

Java Code:

    float[] pointList = null;
    outputBitmap = callJNIFunc(pointList, inputBitmap);

JNI Code:

Bitmap callJNIFunc(JNIEnv *env, jfloatArray pointListInPixels, jobject inputBitmap) {
  pointListInPixels = (env)->NewFloatArray(pointListSize.M * 2);
  env->SetFloatArrayRegion(pointListInPixels, 0, pointListSize.M * 2, pointFloats);
}

我从pass data between Java and C读到这可以通过传递自定义对象来实现。但是,我不太确定如何从jni中为包含像这个

的float数组的java对象这样做
public class CustomObject{
  public  float[] points;
  public float[] getPoints() {
    return points;
  }

  public void setPoints(float[] points) {
    this.points = points;
  }

}

2 个答案:

答案 0 :(得分:0)

查看JNI函数的第一行。

最初,pointListInPixels表示Java对象的地址 - 您的java代码中的float[] pointList

在下一行中,您将其分配给(env)->NewFloatArray,这意味着pointListInPixels不再指向Java中的float[] pointList,而是指向新数组。因此,您对SetFloatArrayRegion的通话无效。它确实用Java修改了一个数组,但是它并没有修改你想要它修改的数组。

这样做的正确方法是让你的JNI函数返回jFloatArray,将你的java代码转换为:

    float[] pointList = callJNIFunc();

和您的JNI代码:

    jFloatArray pointListInPixels = (env)->NewFloatArray(pointListSize.M * 2);
    env->SetFloatArrayRegion(pointListInPixels, 0, pointListSize.M * 2, pointFloats);
    return pointListInPixels;

应根据需要更改方法签名。

答案 1 :(得分:0)

您可以创建容器类来返回值,如下所示:

public class Result{
    public final Bitmap bitmap;
    public final float[] pointListInPixels;

    public Result(Bitmap bitmap, float[] pointListInPixels){
        this.bitmap = bitmap;
        this.pointListInPixels = pointListInPixels;  
    }
}

从jni构造并返回Result对象:

Result callJNIFunc(JNIEnv *env, jfloatArray pointListInPixels, jobject inputBitmap) {
  // load class by name
  jclass cls = env->FindClass("my/package/name/Result");
  if (env->ExceptionOccurred()) return NULL;

  // take constructor by signature
  jmethodID constructorId = env->GetMethodID(cls, "<init>", "(android/graphics/Bitmap, [[F)V");
  if (env->ExceptionOccurred()) return NULL;

  jobject output_bitmap; // create bitmap and implement logic 

  pointListInPixels = (env)->NewFloatArray(pointListSize.M * 2);
  env->SetFloatArrayRegion(pointListInPixels, 0, pointListSize.M * 2, pointFloats);

  // create result object
  jobject result = env->NewObject(cls, constructorId, output_bitmap, pointListInPixels);

  return result;
}

对于此代码示例,您不需要delete对象,因为它们将由java api(在Java堆内部)创建。您可以使用简单元加载器来处理来自此code snippet

的java对象