Forum Stats

  • 3,840,384 Users
  • 2,262,598 Discussions
  • 7,901,256 Comments

Discussions

Retrieving arrays of java class inside C++ code

860480
860480 Member Posts: 8
edited May 16, 2011 6:20PM in Java Native Interface (JNI)
Hi everyone,

Currently i am using JNI for native access. But i am getting some error while retrieving arrays of a java class inside my c++ code. I mean, if my java code is:
package GUI;
public class myClass {
    
    public native test1 classcl();       ///return type is object of class 'test1' (defined below)
    
        public static void main(String[] args)
    {
        System.load("D:\\dot_net\\TestGUI\\debug\\TestGUI.dll");
        myClass obj = new myClass();
        obj.classcl();
        
    }

}

class test1 {
    public int var = 90;
    public byte[] raw = new byte[5];
    
    public byte[] GetByte(){
        return raw;  
}}
then my corresponding implementation in C++ would be:
 JNIEXPORT jobject JNICALL Java_GUI_myClass_classcl
  (JNIEnv *env, jobject obj)
{
	jclass testC;
	jobject objC;
	jint var1;
	jfieldID fid1;

	testC = env->FindClass("GUI/test1");
	fid1 = env->GetFieldID(testC,"var","I");
        objC = env->AllocObject(testC);
        env->SetIntField(objC,fid1,74);             ///// by this the integer field 'var' is accessed and it's value is changed
        return objC;
} 
/*****************DOUBT******************\
You all must have noticed that there is also a byte array named raw inside class test1.
So, my doubt is like I accessed the integer field var of class test1, if i also have to access the byte array(raw) and change it's value, then what would be my code?

I have tried very hard, but somehow not able to achieve this.

Thanking in advance,

Satya Prakash.

Edited by: 857477 on May 14, 2011 3:29 AM

Answers

  • 802316
    802316 Member Posts: 532
    Personally, I would create the Object in Java, as you have done and update that object rather than create another object to return.

    When you create an object in JNI, you just get the object, without a constructor being called. This means you have to find and invoke the constructor method, or atleast duplicate what the constructor does and create the array. i.e. `raw` will be null unless you do. Obviously attempting to access it without creating an array will cause a Segmentation fault.
  • 860480
    860480 Member Posts: 8
    Ok, but i couldn't get you properly.
    I have no constructor inside my 'test1' class. So, why would i require to invoke the default constructor? I mean, when i am creating the object, the default constructor is invoked automatically, right?

    Anyway my actual problem is that i want the equivalent syntax of the following code:

    /**************this is for accessing an integer variable inside my native C++ code*****************\

    testC = env->FindClass("GUI/test1");
    fid1 = env->GetFieldID(testC,"var","I");
    objC = env->AllocObject(testC);
    env->SetIntField(objC,fid1,74); ///// by this the integer field 'var' is accessed and it's value is changed

    So here, if instead of an integer variable it would have been an integer array, then what would have been the equivalent code?
  • jschellSomeoneStoleMyAlias
    jschellSomeoneStoleMyAlias Member Posts: 24,877 Gold Badge
    857477 wrote:
    the default constructor is invoked automatically, right?
    Java does that.

    You are not doing Java. You are doing JNI. And you must call the constructor.
    So here, if instead of an integer variable it would have been an integer array, then what would have been the equivalent code?
    Easiest way to do this is to write Java code that is a pseudo representation of what your JNI code needs to do.

    Then your JNI code must do the same thing.
  • 860480
    860480 Member Posts: 8
    jschell wrote:
    >

    Easiest way to do this is to write Java code that is a pseudo representation of what your JNI code needs to do.
    Then your JNI code must do the same thing.
    Actually, I am completely new to both Java and Jni. So, can you just give me a small example of what you said:
    " a pseudo representation of what your JNI code needs to do". This would be really helpful.

    Thing is, I am having the following Java class:
    /*********************myClass.java*********************\
    public class myClass{

    public native test ret(); //test is another class defined below
    public static void main(String[] args)
    {
    myClass obj = new myClass();
    test obj1 = obj.ret();
    }
    }

    class test{
    public byte[] raw = new byte[5];
    public string str;
    }

    Now, i create myClass.h by using javac and javah in command prompt.
    now my cpp code using jni:
    /*********************myClass.cpp*********************\

    #include "myClass.h"

    JNIEXPORT jobject JNICALL Java_GUI_myClass_classcl
    (JNIEnv *env, jobject obj)
    {
    jclass testC = env->FindClass("test");
    jfieldID fid = env->GetFieldID(testC,"raw","[B");
    jfieldID fid2 = env->GetFieldID(testC,"str","Ljava/lang/String;");
    jmethodID mid = (env)->GetMethodID(testC, "<init>", "()V");
    jobject newObjC = env->NewObject(testC,mid); //as you said, invoking the constructor first

    So, now what to do? How to operate on the variables "raw" and "str" here. That's where I am confused.

    Waiting to hear from you,
    Sattu
  • jschellSomeoneStoleMyAlias
    jschellSomeoneStoleMyAlias Member Posts: 24,877 Gold Badge
    public native test ret();
    That is your JNI method.
    So, now what to do?
    Step 1: Write Java code, not JNI, which is a pseudo (simulation) of what you want to do with Java, only java, in that JNI method.
    Step 2: Use that code as a model to create your actual JNI code.

    Note that step 1 does NOT involve writing C/C++ code. You write Java code. Only.
This discussion has been closed.