tags:

views:

347

answers:

1

I'm currently working on Mangler's Android implementation.

I have a java class that looks like so:

public class VentriloEventData {
 public short type;
 public class _pcm {
  public int   length;
     public short  send_type;
     public int  rate;
     public byte  channels;
 };
 _pcm pcm;
}

The signature for my pcm object:

$ javap -s -p VentriloEventData
...
org.mangler.VentriloEventData$_pcm pcm;
  Signature: Lorg/mangler/VentriloEventData$_pcm;

I am implementing a native JNI function called getevent, which will write to the fields in an instance of the VentriloEventData class. For what it's worth, it's defined and called in Java like so:

public static native int getevent(VentriloEventData data);
VentriloEventData data = new VentriloEventData();
getevent(data);

And my JNI implementation of getevent:

JNIEXPORT jint JNICALL Java_org_mangler_VentriloInterface_getevent(JNIEnv* env, jobject obj, jobject eventdata) {
 v3_event *ev = v3_get_event(V3_BLOCK);
 if(ev != NULL) {
  jclass event_class = (*env)->GetObjectClass(env, eventdata);

  // Event type.
  jfieldID type_field = (*env)->GetFieldID(env, event_class, "type", "S");
  (*env)->SetShortField(
   env, 
   eventdata, 
   type_field, 
   1234
  );

  // Get PCM class.
  jfieldID pcm_field = (*env)->GetFieldID(env, event_class, "pcm", "Lorg/mangler/VentriloEventData$_pcm;");
  jobject pcm = 
  (*env)->GetObjectField(
   env, 
   eventdata, 
   pcm_field
  );
  jclass pcm_class = (*env)->GetObjectClass(env, pcm);

  // Set PCM fields.
  jfieldID pcm_length_field = (*env)->GetFieldID(env, pcm_class, "length", "I");
  (*env)->SetIntField(
   env,
   pcm,
   pcm_length_field,
   1337
  );

  free(ev);
 }
 return 0;
}

The code above works fine for writing into the type field (that is not wrapped by the _pcm class). Once getevent is called, data.type is verified to be 1234 at the java side :)

My problem is that the assertion "pcm != NULL" will fail. Note that pcm_field != NULL, which probably indicates that the signature to that field is correct... so there must be something wrong with my call to GetObjectField. It looks fine though if I compare it to the official JNI docs.

Been bashing my head on this problem for the past 2 hours and I'm getting a little desperate.. hoping a different perspective will help me out on this one.

edit1: This won't work with any nested object, even a simple 'Ljava/lang/String;' will fail.
edit2: Both ExceptionOccurred and ExceptionCheck return JNI_FALSE.
edit3: Won't work with static fields either.

+2  A: 

Well if this is the complete code, then I guess pcm should be NULL. The object pcm is never instantiated, neither on the Java side nor on C++ side.

David Sauter
Oh wow, that's quite embarassing. I was thinking with my C++ mindset, where '_pcm pcm' just means the object is created on the stack... That should've been _pcm pcm = new _pcm(). Have a good laugh and enjoy the 300 rep bounty ;)
Daniel