0

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

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);
}

我从Java 和 C 之间的传递数据中读到,这可以通过传递自定义对象来实现。但是,我不太确定如何从 jni 为包含这样的浮点数组的 java 对象执行此操作

public class CustomObject{
  public  float[] points;
  public float[] getPoints() {
    return points;
  }

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

}
4

2 回答 2

0

查看 JNI 函数的第一行。

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

在下一行中,您将其分配给(env)->NewFloatArray,这意味着在 Java 中pointListInPixels不再指向您float[] pointList,而是指向一个新数组。因此,您的调用SetFloatArrayRegion无效。当然,它会修改 Java 中的数组,但不会修改您希望它修改的数组。

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

    float[] pointList = callJNIFunc();

和您的 JNI 代码:

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

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

于 2017-09-04T11:28:17.470 回答
0

您可以像这样创建用于返回值的容器类:

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

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

Result从 jni构造并返回对象:

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 堆内部)创建。您可以从此代码片段中为 java 对象使用简单的元加载器

于 2017-09-05T07:21:25.810 回答