2013-02-14 3 views
0

네이티브 코드에서 Java 메서드를 호출하려고합니다. 주어진 단계를 따랐습니다. Calling a java method from c++ in Android네이티브 코드에서 java 함수를 호출하는 중 오류가 발생했습니다.

그러나 Java 기능이 호출 된 곳에서 응용 프로그램이 충돌합니다.

package com.example.jnitry; 

import android.os.Bundle; 
import android.app.Activity; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Log.d("MYAPP","Ocreate entered...."); 
     Button btn=(Button) findViewById(R.id.button1); 
     btn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 
       // TODO Auto-generated method stub 
       mainfunc(8); 
      } 
     }); 
    } 

    public void display(byte[] byt){ 
     Log.d("MYAPP", "display() is entered...."); 
     for(int i=0;i<byt.length;i++) 
      Log.d("MYAPP", "byt["+i+"]="+byt[i]); 
     Log.d("MYAPP", "display finished"); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 
    public static native void mainfunc(int n); 

    static 
    { 
     System.loadLibrary("mylib"); 
    } 
} 

내 네이티브 코드는 아래와 같습니다 :

#include <jni.h> 
#include "com_example_jnitry_MainActivity.h" 
#include <android/log.h> 
#include <stdio.h> 

JNIEXPORT void JNICALL Java_com_example_jnitry_MainActivity_mainfunc 
    (JNIEnv *env, jclass obj, jint n){ 

    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","mainfunction entered...",NULL); 
    int i; 
    unsigned char arr[10]; 
    jbyteArray bArray=(*env)->NewByteArray(env,n); 

    jclass cls = (*env)->FindClass(env, "com/example/jnitry/MainActivity"); 
     jmethodID mid = (*env)->GetMethodID(env, cls, "display", "([B)V"); 
     if (mid == 0){ 
      __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","mid==0",NULL); 
      return; 
     } 
     if(bArray==NULL) 
      { __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","bArray==NULL...",NULL); 
       return ; 
      } 
    for(i=0;i<n;i++){ 
     arr[i]=i; 
     __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Iteration number:%d",i); 
    } 

    (*env)->SetByteArrayRegion(env,bArray,0,n,arr); 
    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","bArray successfully created...",NULL); 
    (*env)->CallVoidMethod(env, obj, mid, bArray); 
    __android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Returned from disp() java function.....",NULL); 

} 

내 응용 프로그램 충돌 로그 메시지를 인쇄 한 후 :

02-14 15:37:06.814: D/MYAPP(11584): bArray successfully created... 

을 다음과 같이

내 자바 코드는 아무도 이유를 말해 줄 수 있습니까? 또한이를위한 솔루션을 제공하십시오. 미리 감사드립니다.

참고 : CallVoidMedthodA() 이미 시도 , callByteMethod(), CallObjectMethod() 그러나이 결과는 동일했다.

답변

3

귀하의 네이티브 메소드 mainFunc 정적 방법입니다 - 그것은 유효한 this 포인터를 가지고 있지 않습니다. 한편, display은 인스턴스 메소드입니다. 인스턴스 메소드가 필요합니다.

mainFunc의 두 번째 매개 변수는 실제로 JNI 규칙에 따라 MainActivity의 클래스 개체 포인터입니다. Java 측에서 mainFunc을 nonstatic로 선언하면 이것이 가능합니다.

+0

대단히 고마워 ... 너에게 제안했듯이 정적 키워드를 제거하는 것은 효과가 있었다. – Zax

0

AFAIK CallVoidMethod는 env 인수를 사용하지 않습니다. 최소한 C++에서는.

+0

위 코드는 c입니다. 따라서 모든 jni 함수 호출에서 첫 번째 인수로 env를 전달하는 것은 필수입니다. – Zax

1

나는 이것을 줄 수있다. 그것은 작동합니다. 그러나 C++입니다. (SO 탭 식사 -. 미안)

// it returns NULL in the case of an exception 
// the returned memory is calloc()'d; it's the caller's responsibility to free() it. 
char* changeEncoding(const char*source, int len, int direction) 
{ 
    JNIEnv* env = threadUnsafeInfo.env; 
    jobject obj = threadUnsafeInfo.obj; 

    if (!source) { 
    JNU_ThrowByName(env, "java/lang/NullPointerException", 0); 
    return NULL; 
    } 
    jbyteArray srcArray = env->NewByteArray(len); 

    jclass cls = env->FindClass("com/xxx/Yyy"); 
    jmethodID mid = env->GetMethodID(cls, "convert", "([BI)[B"); 

    if (mid != NULL && srcArray != NULL) { 
    env->SetByteArrayRegion(srcArray, 0, len, (jbyte*)source); 
    env->ExceptionClear(); 

    jbyteArray resArray = (jbyteArray)env->CallObjectMethod(obj, mid, srcArray, direction); 
    if(env->ExceptionOccurred()) { 
     DLOG("exception in convert ([BI)[B"); 
     env->ExceptionDescribe(); 
     //env->ExceptionClear(); // ?? 
     return NULL; 
    } 

    int resultLen = env->GetArrayLength(resArray); 
    char* result = (char*)calloc(2 + resultLen,1); // why 2: a bit of healthy paranoia ain't gonna hurt anyone 
    if (result == 0) { 
     JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); 
     return NULL; 
    } 
    env->GetByteArrayRegion(resArray, 0, resultLen, (jbyte *)result); 
    env->DeleteLocalRef(cls); 
    env->DeleteLocalRef(resArray); 
    env->DeleteLocalRef(srcArray); 
    return result; 
    } else { 
    JNU_ThrowByName(env, "java/lang/NullPointerException", 0); 
    myassert(("method id = 0",0)); 
    } 
    return NULL; 
} 
+0

+1 노력. 내가 CallObjectMethod와 함께 시도했다. ... – Zax

관련 문제