Android NDK C ++ JNI (không tìm thấy triển khai cho bản địa…)


86

Tôi đang cố gắng sử dụng NDK với C ++ và dường như không thể làm đúng quy ước đặt tên phương thức. phương pháp gốc của tôi như sau:

extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
   //
}
}

với tiêu đề được bọc bằng chữ "C" {} aslo bên ngoài.

Mọi thứ biên dịch tốt, tạo tệp .so và sao chép vào thư mục libs trong dự án của tôi, nhưng khi tôi gỡ lỗi và chạy trong Eclipse, tôi tiếp tục nhận được thông báo nhật ký mèo rằng "không tìm thấy triển khai cho bản địa ...". Có điều gì tôi thiếu vì tất cả các ví dụ NDK đều có trong C không?

Cảm ơn.


Bạn có đang tạo sơ khai JNI của mình bằng cách sử dụng javahkhông? Nếu không, bạn nên. :-P
Chris Jester-Young

7
Nhiều khả năng là do bạn không gọiSystem.loadLibrary
IgorGanapolsky

1
Cảm ơn câu hỏi của bạn. Tôi đã học được một điều mới ngày hôm nay.
Shady Mohamed Sherif,

Câu trả lời:


148

Có một số điều có thể dẫn đến "không tìm thấy triển khai". Một là lấy sai tên nguyên mẫu hàm, một là không tải được .so. Bạn có chắc rằng nó System.loadLibrary()đang được gọi trước khi phương thức được sử dụng không?

Nếu bạn chưa JNI_OnLoadxác định một hàm, bạn có thể muốn tạo một hàm và yêu cầu nó đưa ra một thông báo nhật ký chỉ để xác minh rằng lib đang được kéo vào thành công.

Bạn đã tránh được vấn đề phổ biến nhất - quên sử dụng extern "C"- vì vậy đó là lỗi ở trên hoặc một số lỗi chính tả nhẹ. Khai báo Java trông như thế nào?


13
Chúa ơi! Bạn đã tiết kiệm cho tôi hàng giờ làm việc đáng giá - khi đọc bài này, tôi mới nhớ là mình đã tải xong Cuộc gọi danh dự đã nhận xét ...
zeboidlund

11
Bạn cũng đã cứu tôi! Tôi đã kiểm tra bốn lần tên hàm của mình và một vài thứ khác ... nhưng tôi quên "C" bên ngoài, và thậm chí không nhận thấy nó trong câu hỏi!
Qwertie

1
Hiện có trên trang web tài liệu Android: developer.android.com/training/articles/perf-jni.html#faq_ULE
fadden 15/12/12

2
cũng có một trường hợp không ai nói về nó: bạn không thể sử dụng '_' (dấu gạch dưới) trong tên hàm vì dấu gạch dưới được dùng làm dấu phân tách gói. Vì vậy, chỉ có trường hợp lạc đà tên hàm có thể xảy ra
Nulik

2
@Nulik: bạn có thể sử dụng '_' nếu bạn thoát nó thành "_1".
fadden 13/1218

18

Một nguyên nhân khác gây ra lỗi này: tên phương thức gốc chưa được trang trí của bạn không được chứa dấu gạch dưới!

Ví dụ, tôi muốn xuất một hàm C có tên AudioCapture_Ping(). Đây là tờ khai xuất khẩu của tôi trong C:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object);  //Notice the underscore before Ping

Đây là lớp Java của tôi nhập hàm:

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapture_Ping();  // FAILS
    ...

Tôi không thể khiến Android liên kết động với phương thức gốc của mình cho đến khi tôi xóa dấu gạch dưới:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object); 

package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
    private native int AudioCapturePing();  // THIS WORKS!
    ...

5
Sự xuất hiện của '_' trong khai báo ngôn ngữ Java phải được thay thế bằng "_1" trong khai báo gốc. Xem bảng 2-1 trong docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/… .
fadden

1
Rõ ràng là vậy, nhưng tôi đã không thể tự mình tìm ra nó sau vài giờ gỡ lỗi ... Cảm ơn, bạn đã cứu tôi!
George Atsev

@ user1222021 Tôi có một câu hỏi, chúng tôi có thể xuất phương thức cpp cho tất cả các hoạt động trong dự án, chúng tôi có cần chỉ định tên hoạt động trong phương thức trong tệp .cpp không?
Balflear

14

Tôi đã gặp vấn đề tương tự, nhưng với tôi thì lỗi nằm trong tệp Android.mk. Tôi đã có nó:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp 

nhưng nên có cái này:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp 

lưu ý chi tiết + = thay vào đó : =

Tôi hy vọng rằng sẽ giúp.


2
Hoặc bạn có thể thêm tất cả chúng trên một dòng hoặc sử dụng ký tự ngắt dòng `\ '.
IgorGanapolsky

6

Được gọi là extern "C" như được cung cấp trong ví dụ Studio được tạo tự động, nhưng quên đặt toàn bộ phần còn lại của tệp, bao gồm các hàm sau, trong dấu ngoặc vuông {}. Chỉ có chức năng đầu tiên hoạt động.


4

Một lý do khác: Sử dụng LOCAL_WHOLE_STATIC_LIBRARIES thay vì LOCAL_STATIC_LIBRARIES trong android.mk. Điều này ngăn thư viện tối ưu hóa các lệnh gọi API không sử dụng vì NDK không thể phát hiện việc sử dụng các liên kết gốc từ mã java.


1
Sự khác biệt ở đâu: "Sử dụng LOCAL_WHOLE_STATIC_LIBRARIES thay vì LOCAL_STATIC_LIBRARIES trong android.mk"
Josh

4

Có một ví dụ về cpp trong ứng dụng trong ndk: https://github.com/android/ndk-samples/blob/master/hello-gl2/app/src/main/cpp/gl_code.cpp


2
bạn có thể tìm thấy các tập tin cpp trong android-ndk / samples / hello-GL2 là một phần của phân phối Android NDK
Yenchi


1
@pevik Lại chết rồi.
Mygod


liên kết đã chết một lần nữa
dùng13107

2

Sử dụng javah (một phần của Java SDK). Nó là công cụ chính xác cho việc này (tạo tiêu đề .h từ tệp .class).


2

Nếu tên gói của bạn bao gồm ký tự _, bạn nên viết 1 (một) sau ký tự _ như hình dưới đây:

MainActivity.java

package com.example.testcpp_2;

native-lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(

0

Tôi thử tất cả các giải pháp ở trên, nhưng không ai có thể giải quyết lỗi bản dựng của tôi (jni java.lang.UnsatisfiedLinkError: Không tìm thấy triển khai cho ...), cuối cùng tôi thấy rằng tôi quên thêm tệp nguồn verify.cpp của mình vào CMakeList.txt add_library segement (verify.cpp được tự động tạo bằng phím tắt Ctrl + Enter, có thể là tên tệp khác), hy vọng phản hồi của tôi có thể giúp một số người.

môi trường xây dựng của tôi: Gradle + CMake


0

Tôi gặp phải vấn đề tương tự và trong trường hợp của tôi, lý do là tôi đã gạch dưới trong tên gói "RFID_Test". Tôi đã đổi tên Gói và nó hoạt động. Cảm ơn người dùng1222021


-3

Tôi đã phải đối mặt với cùng một vấn đề hai lần. Điều đã xảy ra là điện thoại tôi đã cố gắng khởi động ứng dụng từ Android Studio đã sử dụng cấp API mà tôi chưa tải xuống trong Android Studio.

  1. Nâng cấp Android Studio lên phiên bản mới nhất
  2. Tải xuống API cần thiết từ trong Android Studio
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.