2015-02-20 14 views
5

Tôi rất mới với JNI và tôi đang cố gắng tìm ra cách một số thứ hoạt động trước khi tôi chuyển mã C++ iOS của mình sang nó. Tôi đã thành công trong việc lấy một trong những mẫu NDK làm việc trong Android studio và tôi có thể thấy cách Java có thể gọi các hàm C++.NDK của Android: Gọi các hàm Java từ C++

Tôi đã tìm kiếm và lấy các đoạn mã, nhưng tôi không thể làm cho nó hoạt động trong quá trình triển khai cụ thể của mình.

Chỉ để kiểm tra xem mọi thứ hoạt động như thế nào tôi thiết lập chức năng nhật ký văn bản đơn giản trong java và tôi đang cố gắng gọi nó từ mã gốc nhưng tôi đã gặp sự cố.

Đây là chức năng của tôi Java:

public static void log(String s){ 
     Log.d("Native", s); 
} 

Và C++:

void Log(std::string s){ 

    JNIEnv *env; 
    g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); 

    jstring jstr1 = env->NewStringUTF(s.c_str()); 

    jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib"); 
    jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V"); 

    jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1); 
} 

Từ những gì tôi đã nhìn thấy với các ví dụ khác nhau này nên làm việc, nhưng nó ném một lỗi:

29835-29849/com.android.gl2jni A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 29849 (Thread-17371) 

Tôi có thiếu gì đó không?

EDIT:

Tôi đã đổi nó thành GetStaticMethodID. Nhưng sau khi đăng nhập tiến độ thực hiện chức năng tôi đã phát hiện ra rằng dòng thất bại là:

g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); 

Mà tôi tìm là vì g_JavaVM được thiết lập như static JavaVM* g_JavaVM = NULL; và sau đó không bao giờ chạm vào một lần nữa. Tôi đoán tôi cần phải đặt biến này, nhưng làm thế nào?

+0

Bạn có thể thêm __android_log_print (ANDROID_LOG_DEBUG, "myApp", "msg xxx") trước mỗi dòng và tìm ra nguyên nhân gây SIGSEGV. –

+0

Tôi chưa thử nghiệm mã, nhưng vì có một 'GetStaticMethodID' -function trong' JNIEnv', tôi sẽ mạo hiểm đoán rằng cuộc gọi của bạn đến 'GetMethodID' không thể tìm thấy bất kỳ phương thức không tĩnh nào khớp với chữ ký của bạn và sau đó trả về null, mà bạn không kiểm tra. – zenzelezz

+0

Tôi đã thay đổi một số mã và thêm một số chi tiết. – Bananable

Trả lời

7

Một phần vấn đề của tôi là tôi đã không khởi tạo JavaVM. Một phần khác là tôi đã sử dụng C++, nhưng tôi đã cố gắng sử dụng các hàm C.

Mã làm việc là:

Java:

public static void log(String s){ 
     Log.d("Native", s); 
} 

C++:

void Log(std::string s){ 

    JNIEnv *env; 
    g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); 

    jstring jstr1 = env->NewStringUTF(s.c_str()); 

    jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib"); 
    jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V"); 

    jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1); 
} 

//In some initialization function with Environment variable 

env->GetJavaVM(&g_JavaVM); 

Hy vọng rằng điều này có thể giúp đỡ người khác với cùng một vấn đề.

+2

Bạn có lỗi đánh máy, nó phải là 'CallStaticVoidMethod()'. – Pol

+0

Tôi đã sử dụng javac Foo.java theo sau là javap -s Foo để lấy tên bị xé. Xem http://www.rgagnon.com/javadetails/java-0286.html – Glenn