使用c结构成员填充java类成员

时间:2013-05-01 14:11:38

标签: android java-native-interface

我有一个与此类似的代码

struct time
{
    long milliscnds;
    int  secs;
}

在我的java文件中,我有类似的东西

class jtime
{
    long millscnds;
    int  secs;
}

new jtime time = new jtime();

public int native getTimeFromC(object time);

在本地课程中

getTimeFromc(JNIEnv* env, jobject thiz,jobject jtime)
 {
   struct time *mytime = getTime(); 

  now to fill the jtime with mytime
 }

建议吗?

2 个答案:

答案 0 :(得分:1)

您可以简化Java类和所需的JNI代码。

目前,您的原生方法存在一些问题:

public int native getTimeFromC(object time);
  1. 参数为Object,但应为jtime
  2. 返回值似乎没有用处。
  3. 由于该方法完全初始化jtime对象,为什么不创建并返回jtime对象?
  4. 这个类定义有一个工厂方法来创建对象,一个构造函数可以从JNI端移动一些初始化工作。

    public class jtime {
    
        long millscnds;
        int  secs;
    
        public jtime(long millscnds, int secs) {
            this.millscnds = millscnds;
            this.secs = secs;
        }
    
        public native static jtime FromC();
    }
    

    工厂方法可以这样实现:

    JNIEXPORT jobject JNICALL Java_jtime_FromC
      (JNIEnv * env, jclass clazz)
    {
        struct time *mytime = getTime();
    
        jmethodID ctor = (*env)->GetMethodID(env, clazz, "<init>", "(JI)V");
        jobject obj = (*env)->NewObject(env, clazz, ctor, mytime->milliscnds, mytime->secs);
    
        return obj;
    }
    

    提示javap工具与javah类似,但显示非本机方法的签名。使用javap -s jtime,您可以看到构造函数的签名。

答案 1 :(得分:0)

如下所示:

void getTimeFromc(JNIEnv* env, jobject thiz, jobject jtime)
{
    struct time *mytime = getTime(); 

    // now to fill the jtime with mytime
    jclass jtimeClazz = (*env)->GetObjectClass(jtime); // Get the class for the jtime object
    // get the field IDs for the two instance fields
    jfieldID millscndsFieldId = (*env)->GetFieldID(jtimeClazz, "milliscnds", "J"); // 'J' is the JNI type signature for long
    jfieldID secsFieldId = (*env)->GetFieldID(jtimeClazz, "secs", "I"); // 'I' is the JNI type signature for int
    // set the fields
    (*env)->SetLongField(jtime, millscndsFieldId, (jlong)mytime.milliscnds);
    (*env)->SetIntField(jtime, secsFieldId, (jint)mytime.secs);
}

理想情况下,您应该缓存millscndsFieldIdsecsFieldId的值,因为它们在执行期间不会更改(如果您jtimeClazz,也可以缓存NewGlobalRef)。

此处记录了所有JNI功能:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html