如何使用 JNI 创建对象?

我需要使用 NDK 和 JNI 在 Android 应用程序中实现一些功能.

I need to implement some functions into an Android application using NDK and thus JNI.

下面是我写的 C 代码:

Here's the C code, with my concerns, that I wrote:

#include <jni.h>
#include <stdio.h>

jobject
Java_com_example_ndktest_NDKTest_ImageRef(JNIEnv* env, jobject obj, jint width, jint height, jbyteArray myArray)
{
    jint i;
    jobject object;
    jmethodID constructor;
    jobject cls;
    cls = (*env)->FindClass(env, "com/example/ndktest/NDKTest/Point");

//what should put as the second parameter? Is my try correct, according to what
//you can find in .java file? I used this documentation: http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp16027

    constructor = (*env)->GetMethodID(env, cls, "<init>", "void(V)");
//http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp16660
//Again, is the last parameter ok?

    object = (*env)->NewObject(env, cls, constructor, 5, 6);
//I want to assign "5" and "6" to point.x and point.y respectively.
    return object;
}    

我的问题或多或少在代码中得到了解释.也许还有:函数(jobject)的返回类型是否正常?

My problems are more or less explained inside the code. Maybe also: is the return type of the function (jobject) ok?

现在是 NDKTest.java:

Now the NDKTest.java:

package com.example.ndktest;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;

public class NDKTest extends Activity {
    /** Called when the activity is first created. */
    public native Point ImageRef(int width, int height, byte[] myArray);
    public class Point
    {

        Point(int myx, int myy)
        {
            x = myx;
            y = myy;
        }

        int x;
        int y;
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {

         super.onCreate(savedInstanceState);
         TextView tv = new TextView(this);
         byte[] anArray = new byte[3];
         for (byte i = 0; i < 3; i++)
             anArray[i] = i;
         Point point = ImageRef(2, 3, anArray);
         tv.setText(String.valueOf(point.x));
            setContentView(tv);     
    }



    static
    {
       System.loadLibrary("test");
    }
}

当我尝试运行代码时,它不起作用.

When I try to run the code, it doesn't work.

推荐答案

既然 Point 是一个内部类,那么获取它的方法是

Since Point is an inner class, the way to get it would be

jclass cls = (*env)->FindClass(env, "com/example/ndktest/NDKTest$Point");

内部类的 $ 约定在权威规范中并没有真正清楚地记录,但它根植于如此多的工作代码中,不太可能改变.不过,如果您将 JNI 代码限制为使用顶级类,它会感觉更加健壮.

The $ convention for inner classes is not really clearly documented in the authoritative specs, but is entrenched in so much working code that it's unlikely to change. Still, it would feel somewhat more robust if you restricted your JNI code to work with top-level classes.

您需要一个将两个整数作为参数的构造函数.其签名是 (II)V,所以:

You want a constructor that takes two ints as arguments. The signature for that is (II)V, so:

constructor = (*env)->GetMethodID(env, cls, "<init>", "(II)V");

下一次,在你的代码中加入一些错误处理,这样你就会知道它的哪一部分不起作用!

Next time, include some error handling in your code, such that you'll have a clue which part of it doesn't work!

相关文章