Android의 C ++에서 Java 메서드 호출


91

Java가 네이티브 메서드를 호출하는 동안 C ++에서 간단한 Java 메서드 호출을 얻으려고합니다. 다음은 Java 코드입니다.

public class MainActivity extends Activity {
    private static String LIB_NAME = "name";

    static {
        System.loadLibrary(LIB_NAME);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView) findViewById(R.id.textview);
        tv.setText(this.getJniString());
    }

    public void messageMe(String text) {
        System.out.println(text);
    }

    public native String getJniString();
}

Java에서 네이티브 messageMegetJniString*메서드를 호출 하는 과정에서 네이티브 코드에서 메서드 를 호출하려고합니다 .

native.cpp :

#include <string.h>
#include <stdio.h>
#include <jni.h>

jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj, jint depth ){

//    JavaVM *vm;
//    JNIEnv *env;
//    JavaVMInitArgs vm_args;
//    vm_args.version = JNI_VERSION_1_2;
//    vm_args.nOptions = 0;
//    vm_args.ignoreUnrecognized = 1;
//
//    // Construct a VM
//    jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

    // Construct a String
    jstring jstr = env->NewStringUTF("This string comes from JNI");
    // First get the class that contains the method you need to call
    jclass clazz = env->FindClass("the/package/MainActivity");
    // Get the method that you want to call
    jmethodID messageMe = env->GetMethodID(clazz, "messageMe", "(Ljava/lang/String;)V");
    // Call the method on the object
    jobject result = env->CallObjectMethod(jstr, messageMe);
    // Get a C-style string
    const char* str = env->GetStringUTFChars((jstring) result, NULL);
    printf("%s\n", str);
        // Clean up
    env->ReleaseStringUTFChars(jstr, str);

//    // Shutdown the VM.
//    vm->DestroyJavaVM();

    return env->NewStringUTF("Hello from JNI!");
}

클린 컴파일 후 앱이 다음 메시지와 함께 중지됩니다.

ERROR/AndroidRuntime(742): FATAL EXCEPTION: main
        java.lang.NoSuchMethodError: messageMe
        at *.android.t3d.MainActivity.getJniString(Native Method)
        at *.android.t3d.MainActivity.onCreate(MainActivity.java:22)

분명히 메서드 이름이 잘못되었음을 의미하지만 나에게는 괜찮아 보입니다.


21
질문과 솔루션을 더 쉽게 읽고 커뮤니티에 더 유용 할 수 있도록 일반적인 답변으로 솔루션을 게시하십시오. 이미 답변 한 다른 사람들과 협력하여 답변을 완료 할 수도 있습니다.
misiu_mp 2013

@Denys : 나는 당신의 코딩을 따랐지만이 오류가 발생합니다 : java.lang.UnsatisfiedLinkError : getJniString. 이 오류를 수정할 수 있습니까?
Huy Tower

@AlexTran, 오래 전 이었지만 오류로 판단하면 아마도 철자가 틀렸거나 getJniStringjava 또는 c에서 메소드를 링크하지 않았습니다 . 아마도 시스템 가져 오기로 자바에 제대로 연결 C 코드에 있는지 확인하십시오 (srsly 기억하지 않는 모든 지금이 물건 : P)
데니스 S.

1
c에서 Java 메서드를 어떻게 호출합니까? 그것은 노골적으로 onCreate당신의 네이티브 C를 호출하는 자바의 방법입니다.
John

환경 (env) 변수로 실행할 때 '->'의 기본 피연산자에 비 포인터 유형 'JNIEnv 가 있습니다. 또한 JNI에서 Java 계층으로의 콜백과 같이 env * 변수없이 수행하려면 어떻게해야합니까! 어떠한 제안!
CoDe 2015 년

답변:


45

객체 메서드 인 경우 객체를에 전달해야합니다 CallObjectMethod.

jobject result = env->CallObjectMethod(obj, messageMe, jstr);

당신이했던 일은 jstr.messageMe().

귀하는 void 메서드이므로 다음을 호출해야합니다.

env->CallVoidMethod(obj, messageMe, jstr);

결과를 반환하려면 JNI 서명 ( 반환 유형 ()V의 메서드를 의미 void)과 Java 코드의 반환 유형을 변경해야합니다.


제 PS 때문에 어떻게 그렇게하는지 안내 해주세요 :)
Denys S.

나는 당신이 제안한 것과 같은 결과를 얻습니다.
Denys S. 2011 년

1
실제로 각각 다른 반환 유형을 가진 CallVoidMethod, CallObjectMethod 등이 있습니다. messageMe 메서드는 (Ljava / lang / String;) V이므로 CallVoidMethod를 사용해야합니다.
Matthew Willis 2011 년

2
당신은 아마 받고있어 오류가 (Java 코드에서) 자바 네이티브 메소드는 무효 반환 형식의 아마되지 않습니다 그래서 대해서 GetMethodID에 의해 발견되고 있지 않음을 나타냅니다합니다
매튜 윌리스

10

Denys S. 가 질문 게시물에 게시 한 솔루션 :

나는 C에서 C ++ 로의 변환 (기본적으로 env가변적 인 것) 으로 그것을 꽤 엉망으로 만들었지 만 C ++에 대한 다음 코드로 작업했습니다.

#include <string.h>
#include <stdio.h>
#include <jni.h>

jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){

    jstring jstr = (*env)->NewStringUTF(env, "This comes from jni.");
    jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity");
    jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
    jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr);

    const char* str = (*env)->GetStringUTFChars(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :)
    printf("%s\n", str);

    return (*env)->NewStringUTF(env, str);
}

그리고 자바 메소드에 대한 다음 코드 :

    public class MainActivity extends Activity {
    private static String LIB_NAME = "thelib";

    static {
        System.loadLibrary(LIB_NAME);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView) findViewById(R.id.textview);
        tv.setText(this.getJniString());
    }

    // please, let me live even though I used this dark programming technique
    public String messageMe(String text) {
        System.out.println(text);
        return text;
    }

    public native String getJniString();
}

마십시오 native방법은 정적해야?
IgorGanapolsky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.