JVM object referenced by 'foo_model' is of type 'Class<Foo>' and it does not have access to field 'float a' declared in 'Foo'

Viewed 448

Why can I not access the public members on my data class?

In my test Android Kotlin/NDK app, GetFloatField is reporting

JVM object referenced by 'foo_model' is of type 'Class' and it does not have access to field 'float a' declared in 'Foo'.

Class<Foo> is a data class I defined with all public members.

I'm new to Kotlin, so this app is just an exercise for me to learn how to pass custom structs to and from the native layer.

MainActivity.kt

package com.example.structtest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

public data class Foo(var a: Float = 3.14f, var b: Int = 10)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var f = Foo(3.14f, 10)

        var dFoo = doubleFoo(f)
        sample_text.text = "foo.a = ${dFoo.a}, foo.b=${dFoo.b}"
    }

    external fun doubleFoo(_foo : Foo): Foo

    companion object {
        // Used to load the 'native-lib' library on application startup.
        init {
            System.loadLibrary("native-lib")
        }
    }
}

native-lib.cpp:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_structtest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jobject JNICALL
Java_com_example_structtest_MainActivity_doubleFoo(
        JNIEnv* env,
        jobject /* this */,
        jobject _foo) {

    auto foo_model = env->GetObjectClass(_foo);
    auto const foo_float_field = env->GetFieldID(foo_model, "a", "F");
    auto const foo_int_field   = env->GetFieldID(foo_model, "b", "I");

    //
    // This is where I get the error, on these GetFloatField calls
    //
    auto const foo_float = env->GetFloatField(foo_model, foo_float_field);
    auto const foo_int = env->GetFloatField(foo_model, foo_int_field);

    // I'm not even sure if these lines do anything.
    // I suspect the error being thrown above crashes the app before these are executed
    auto new_foo_model  = env->FindClass("com/example/structtest/Foo");
    auto constructor = env->GetMethodID(new_foo_model, "<init>", "(FI)V");
    auto new_foo = env->NewObject(new_foo_model, constructor);

    return new_foo;
}
1 Answers

You are trying to read the field a from the Class object describing Foo (foo_model in your code) instead of directly from the Foo instance (_foo in your code).

Change env->GetFloatField(foo_model, foo_float_field); to

env->GetFloatField(_foo, foo_float_field);
Related