jni编程

mbyulnm0  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(503)

我是jni编程的新手。我想将一个float数组从java传递到jni,动态地为jni端的float数组分配足够的内存,在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之间的pass数据中了解到,这可以通过传递自定义对象来实现。但是,我不太清楚如何从jni为包含如下浮点数组的java对象执行此操作

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

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

}
2lpgd968

2lpgd9681#

您可以创建容器类以返回如下值:

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 对象,因为它们将由javaapi(在java堆内部)创建。您可以使用这个代码片段中的简单元加载器来处理java对象

4uqofj5v

4uqofj5v2#

看看jni函数的第一行。
起初, pointListInPixels 表示java对象的地址 float[] pointList 在java代码中。
在下一行中,您将其分配给 (env)->NewFloatArray ,也就是说 pointListInPixels 不再指向你的 float[] pointList 在java中,但要使用一个新数组。因此,你的电话 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;

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

相关问题