Android JNI get Two Fields from Java class

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

Before I post any code or anything, let me explain what I'm trying to accomplish: what I'm trying to do is get load shaders from an assets folder, and pass an array of PongDroidShader objects to C++ so it can compile and load them.

In my Java class, I have a function which goes through each shader file in the shaders folder and parses it loads it into a String object, while also checking for what kind of shader type it is via its file extension (.e.g, a vertex would have a .vert extension). Once I've accomplished that, I then send it to my native compileShaders function, which takes the array of PongDroidShader objects, and the size of the array.

After that, I parse and link the shaders from the JNI code.

So far, I'm having trouble getting the JNI to recognize the Java code and load it into variables. What I have so far is as follows:

Java Code

public final class PongDroidShader {     public String mShaderSrc;     public ShaderType mType; }  private class ShaderHandler {           ...          private native void compileShaders(PongDroidShader[] shaders, int shaderCount);          ...

JNI/C++ Code

JNIEXPORT void JNICALL Java_com_grepwise_pongdroid_PongDroid_00024ShaderHandler_compileShaders   (JNIEnv * env, jobject obj, jobjectArray shaders, jint sizeOfShaders) {      for( int i = 0; i < sizeOfShaders; ++i )     {         jclass clazz = env->FindClass( "com/grepwise/pongdroid/PongDroidShader" );         jclass shaderTypeEnum = env->FindClass( "com/grepwise/pongdroid/ShaderType" );          jfieldID field = env->GetFieldID( clazz, "mType", "ShaderType" );          jobject shader = env->GetObjectArrayElement( shaders, i );          const jchar jShaderChr = env->GetCharField( shader, env->GetFieldID( clazz, "mShaderSrc", "java/lang/String" ) );          jstring jShaderStr = env->NewString( &jShaderChr, sizeof( jShaderChr ) );          const char* shaderStr = env->GetStringUTFChars( jShaderStr, 0 );          //TODO implement GL Shader Manipulation and Allocation here          optim::Config::Log::info( "Testing shader: %s", shaderStr );          delete shaderStr;     }  }

I've omitted a lot of what exists in the code base just for the sake of simplicity. Note that even though compileShaders isn't shown being called, it is called by the activity class which wraps its parent class as an inner private class.

So far, my log output is as follows:

04-25 22:20:56.267 11985 11985 D dalvikvm: Trying to load lib /data/data/com.grepwise.pongdroid/lib/libnativepd.so 0x4051c800 04-25 22:20:56.275 11985 11985 D dalvikvm: Added shared lib /data/data/com.grepwise.pongdroid/lib/libnativepd.so 0x4051c800 04-25 22:20:56.322 11985 11985 D dalvikvm: GetFieldID: unable to find field Lcom/grepwise/pongdroid/PongDroidShader;.mType:ShaderType 04-25 22:20:56.322 11985 11985 D dalvikvm: GetFieldID: unable to find field Lcom/grepwise/pongdroid/PongDroidShader;.mShaderSrc:java/lang/String 04-25 22:20:56.330 11985 11985 I dalvikvm:   at com.grepwise.pongdroid.PongDroid$ShaderHandler.compileShaders(Native Method) 04-25 22:20:56.330 11985 11985 I dalvikvm:   at com.grepwise.pongdroid.PongDroid$ShaderHandler.access$1(PongDroid.java:128) 04-25 22:20:56.330 11985 11985 I dalvikvm:   at com.grepwise.pongdroid.PongDroid.onCreate(PongDroid.java:72)

回答1:

I believe you should be using this to get your fields:

env->GetFieldID( clazz, "mType", "Lcom/grepwise/pongdroid/ShaderType;" ); env->GetFieldID( clazz, "mShaderSrc", "Ljava/lang/String;" )

And move the class & field getting out of the loop.

EDIT: Also this:

const jchar jShaderChr = env->GetCharField(...)

to get String value from mShaderSrc is wrong.

You should be using:

jstring jShaderStr = (jstring)env->GetObjectField(...); const char* shaderSrc = env->GetStringUTFChars(jShaderStr, 0); // ... here use shaderSrc env->ReleaseStringUTFChars(hShaderStr, shaderSrc);


回答2:

you must get private field from instance, and pass the signature as third argument.

jfieldID field = env->GetFieldID( obj, "mShaderSrc", "Ljava/lang/String;" );


回答3:

I solved the problem: Eclipse wasn't recognizing my classpath. If anyone is having similar issues, then they need to go to Window->Preferences->Java->Build Paths->Classpath, and add the classpath to the Android SDK platform they are using, as well as the path to their project's class root (e.g. $PROJECT_ROOT/bin/classes).



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!