利用JNI我们可以在C++代码中调用Java类的方法,我在网上查看资料做了一个验证的小例子,多数方法调用都没问题,除了用数组作参数的方法,在C++端执行有数组作参数的方法时老是报致命错误,说是返回类型不对,但编译是可以通过的。
现在截取代码如下,请高手帮我看看错在哪里:
Java代码:
//Demo.javaimport java.util.*;
import java.lang.*;
public class Demo {
 
 public static int COUNT = 8;
 public String msg = "still";
 public int nmsg = 9; 
 public int[] counts = new int[5];
 public Date date; 
 
 public Demo(){
 }
 
 public Demo(String msg){
   System.out.println("<init>:" + msg);
   for(int i=0;i<5;i++)
    counts[i]=2*i+1;
   this.msg = msg;
   this.nmsg = 10;
 
//   date = new Date();
//   date.setYear(2005);
//   date.setMonth(11);
//   date.setDate(25);
 }
 
 
 public String GetMessage(){
  System.out.println("GetMessage:" + msg);
  return msg;
 }
 
 public void SetMessage(String msg, int nmsg){
  this.msg = msg;
  this.nmsg = nmsg;
  System.out.println("SetMessage:" + msg);
  System.out.println("nmsg:" + nmsg);
  
 }
 
 public int[] GetCounts(){                  //就是这个方法调用有问题
  System.out.println("GetCounts:" + msg);
  return counts;
 } public void SetCounts(int[] counts){
  System.out.println("SetCounts:" + msg);
  this.counts = counts;  
 }
  public void throwExcp() throws IllegalAccessException {
    throw new IllegalAccessException("exception occur.");
  } 
  
  public  static void main(String[] args)
  {
   Demo d = new Demo("abc");
   int[] count = new int[5];
   for(int i=0;i<5;i++)
   count[i]=10*i;
   d.SetCounts(count);        //java中调用是可以的
   for(int i=0;i<5;i++)
   System.out.println("count["+i+"]= "+d.GetCounts()[i]); 
   d.show();
  }
}
C++代码:#include "stdafx.h"
#include <jni.h>
#include <assert.h>
#pragma comment(lib, "jvm.lib")int main(int argc, char* argv[])
{
 JavaVMOption options[3];
 JNIEnv *env = NULL;
 JavaVM *jvm = NULL;
 JavaVMInitArgs vm_args;
 jclass cls;
 jmethodID mid;
 jfieldID fid; // sets System Properties specific to VM
 options[0].optionString = "-Djava.compiler=NONE";
 options[1].optionString = "-Djava.class.path=.;";
 options[2].optionString = "-verbose:jni";
 vm_args.version = JNI_VERSION_1_2;
 vm_args.nOptions = 3;
 vm_args.options = options;
 vm_args.ignoreUnrecognized = JNI_TRUE;
 
 jint nRetStatus = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
 assert( JNI_ERR != nRetStatus);
 
 cls = env->FindClass("Demo");
 assert( 0 != cls);
...........//中间省略其他的调用//
...........//保留报错的方法调用//
 
 //Call Setcounts  就是这个方法调用出错了
 const jsize len = 5;
 const jsize start = 0;
 
 jintArray arrint = env->NewIntArray(len);
 
jsize j;                                           //
/* 获取数组对象的元素个数 */                       //
int lenth = env->GetArrayLength(arrint);           //查看新建的jintarry
/* 获取数组中的所有元素 */                         //是否创建成功 
elems = env-> GetIntArrayElements(arrint, 0);      //
for(j=0; j< lenth; j++)                            //
printf("ELEMENT %d IS %d\n", j, elems[j]);         //
env->ReleaseIntArrayElements(arrint, elems, 0);    //
 jint pbuf[len] = {90, 91, 92, 93, 94}; env->SetIntArrayRegion(arrint, start, len, pbuf);          //拷贝数组pbuf到arrint
 
/* 获取数组对象的元素个数 */                       //
lenth = env->GetArrayLength(arrint);               //
/* 获取数组中的所有元素 */                         //查看拷贝是否成功
elems = env-> GetIntArrayElements(arrint, 0);      //结果是arrint中已成功
for(j=0; j< lenth; j++)                            //拷贝为pbuf中的数值
printf("ELEMENT %d IS %d\n", j, elems[j]);         //
env->ReleaseIntArrayElements(arrint, elems, 0);    //
 mid = env->GetMethodID(cls, "SetCounts", "([I)V"); assert(0 != mid); // jclass ocls = env ->GetObjectClass(demo);
// mid = env->GetMethodID(ocls,"SetCounts","([I)V");
//估计参数使用有问题
 env->CallObjectMethod(demo, mid, arrint);     //程序执行就是在这里出错鸟~_~!
 
 
 elems = env->GetIntArrayElements(arrint, 0);
 env->ReleaseIntArrayElements(arrint, elems, 0);
  //Call GetCounts     得到数组值的方法调用是正常的 不过目前得到是在Java中初始的值
 mid = env->GetMethodID(cls, "GetCounts", "()[I");
 assert(0 != mid);
 jintArray arrret = (jintArray)  env->CallObjectMethod(demo, mid);
 jsize nlen = env->GetArrayLength(arrret);
 elems = env->GetIntArrayElements(arrret, 0);
 for(i =0 ;i < nlen; i++)
 {
  printf("Element %d is  %d\n", i, *(elems+i));
 } 
 env->ReleaseIntArrayElements(arrret, elems, 0);  //UnLoad JavaVM
 jvm->DestroyJavaVM(); 

 printf("结束!");
 return 0;
}代码中出问题的地方我已作注释,希望碰到过类似问题的朋友近来讨论,并请高手指点,先谢谢了!!!

解决方案 »

  1.   

    你调用了CallObjectMethod而你的返回值不是jobject(Object) 而是 int[]
      

  2.   

    这里也有些JNI的文章,喜欢的话可以看看:http://www.graphics.net.cn/article/java/java_jni_vc6.asphttp://www.graphics.net.cn/article/java/java_jni_string.asphttp://www.graphics.net.cn/article/java/java_jni_skill.asphttp://www.graphics.net.cn/article/java/java_jni_skill_2.asphttp://www.graphics.net.cn/article/java/java_jni.asp
      

  3.   

    问题已经解决了
    在JAVA中 SetCount是void型的  所以应该CallVoidMethod()。这个低级错误烦死我啦!!
    谢谢windcao,也谢谢perfervid:)
      

  4.   

    呵呵,我到想请教楼主一个问题,int [] 是否被当作jobject处理呢??