Android NDK C ++ JNI (네이티브에 대한 구현 없음…)


87

C ++에서 NDK를 사용하려고하는데 메서드 명명 규칙을 올바르게 얻을 수없는 것 같습니다. 내 기본 방법은 다음과 같습니다.

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

헤더가 extern "C"{}로 래핑되어 있습니다.

모든 것이 잘 컴파일되고 .so 파일이 생성되고 내 프로젝트 아래의 libs 폴더에 복사되지만 Eclipse에서 디버그하고 실행할 때 "기본에 대한 구현을 찾을 수 없음 ..."이라는 로그 고양이 메시지가 계속 표시됩니다. 모든 NDK 예제가 C에 있기 때문에 내가 놓친 것이 있습니까?

감사.


사용하여 JNI 스텁을 생성하고 javah있습니까? 그렇지 않다면 그래야합니다. :-P
Chris Jester-Young

7
전화를하지 않았기 때문일 가능성이 큽니다System.loadLibrary
IgorGanapolsky 2016 년

1
질문 해주셔서 감사합니다. 오늘 새로운 것을 배웠습니다.
Shady Mohamed Sherif

답변:


148

"구현을 찾을 수 없음"으로 이어질 수있는 몇 가지 사항이 있습니다. 하나는 함수 프로토 타입 이름을 잘못 받고 다른 하나는 .so를 전혀로드하지 못하는 것입니다. 당신이 확인되는 System.loadLibrary()방법을 사용하기 전에 호출되고?

JNI_OnLoad정의 된 함수 가없는 경우 라이브러리를 성공적으로 가져 왔는지 확인하기 위해 하나를 만들고 로그 메시지를 뱉어 내도록 할 수 있습니다.

이미 가장 일반적인 문제 (사용하는 것을 잊음)를 피 extern "C"했으므로 위의 내용이거나 약간의 철자 오류입니다. Java 선언은 어떻게 생겼습니까?


13
예수! 당신은 저에게 작업 시간을 절약했습니다.이 글을 읽고 저는 방금 loadLibrary 호출이 주석 처리 된 것을 기억했습니다 ...
zeboidlund

11
당신도 저를 구했습니다! 함수 이름과 다른 몇 가지 사항을 4 배로 확인했지만 extern "C"를 잊어 버렸고 질문에서도 알아 차리지 못했습니다!
Qwertie


2
아무도 말하지 않은 경우가 있습니다. 밑줄은 패키지 구분자로 해석되기 때문에 함수 이름에 '_'(밑줄)을 사용할 수 없습니다. 따라서 카멜 케이스 함수 이름 만 가능합니다
Nulik

2
@Nulik : "_1"로 이스케이프 하면 '_'를 사용할 수 있습니다 .
fadden

18

이 오류의 추가 원인 : 데코 레이팅되지 않은 네이티브 메서드 이름에 밑줄이 없어야합니다!

예를 들어,라는 C 함수를 내보내고 싶었습니다 AudioCapture_Ping(). 다음은 C로 된 내 수출 선언입니다.

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

함수를 가져 오는 Java 클래스는 다음과 같습니다.

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

밑줄을 제거 할 때까지 Android가 내 네이티브 메서드에 동적으로 연결되도록 할 수 없습니다.

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
Java 언어 선언에서 발생하는 '_'는 원시 선언에서 "_1"로 대체되어야합니다. docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/…의 표 2-1을 참조하십시오 .
fadden

1
너무 당연하지만 몇 시간 동안 디버깅을 했는데도 스스로 알아 내지 못했습니다. 감사합니다. 저를 구했습니다!
George Atsev

@ user1222021 질문이 있습니다. 프로젝트의 모든 활동에 대해 cpp 메소드를 내보낼 수 있습니까? .cpp 파일의 메소드에 활동 이름을 지정해야합니까?
Balflear

14

나는 같은 문제가 있었지만 나에게 오류는 Android.mk 파일에있었습니다. 그걸 가졌어:

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

하지만 다음이 있어야합니다.

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

대신 + = 세부 사항을 참고하십시오 : =

도움이 되었기를 바랍니다.


2
또는 모두 한 줄에 추가하거나`\`줄 바꿈 문자를 사용할 수 있습니다.
IgorGanapolsky

6

자동 생성 된 Studio 예제에 제공된대로 extern "C"라고 부르지 만 다음 함수를 포함하여 파일의 전체 나머지 부분을 {} 대괄호로 감싸는 것을 잊었습니다. 첫 번째 기능 만 작동했습니다.


4

추가 이유 : android.mk에서 LOCAL_STATIC_LIBRARIES 대신 LOCAL_WHOLE_STATIC_LIBRARIES를 사용하세요. 이렇게하면 NDK가 자바 코드에서 네이티브 바인딩 사용을 감지 할 수 없기 때문에 라이브러리가 사용되지 않는 API 호출을 최적화하지 못합니다.


1
차이점은 다음과 같습니다. "android.mk에서 LOCAL_STATIC_LIBRARIES 대신 LOCAL_WHOLE_STATIC_LIBRARIES 사용"
Josh

4

2
당신은 안드로이드 NDK 유통의 일부입니다 안드로이드 NDK / 샘플 / 안녕하세요-GL2에서 CPP 파일을 찾을 수 있습니다
Yenchi


1
@pevik 또 죽었어.
Mygod


링크는 다시 죽었
user13107

2

javah (Java SDK의 일부)를 사용하십시오. 이를위한 도구입니다 (.class 파일에서 .h 헤더 생성).


2

패키지 이름에 _ 문자가 포함되어 있으면 아래와 같이 _ 문자 뒤에 1 (one)을 써야합니다.

MainActivity.java

package com.example.testcpp_2;

native-lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(

0

위의 모든 솔루션을 시도했지만 아무도 내 빌드 오류 (jni java.lang.UnsatisfiedLinkError : No implementation found for ...)를 해결할 수 없습니다. 드디어 verify.cpp 소스 파일을 CMakeList.txt에 추가하는 것을 잊었습니다. add_library segement (verify.cpp는 Ctrl + Enter 단축 키, 아마도 다른 파일 이름으로 자동 생성됨), 내 응답이 도움이되기를 바랍니다.

내 빌드 환경 : Gradle + CMake


0

나는 같은 문제에 직면했고, 제 경우에는 패키지 이름 "RFID_Test"에 밑줄이 있었기 때문입니다. 저는 패키지 이름을 바꾸고 작동했습니다. 감사합니다 user1222021


-3

나는 같은 문제에 두 번 직면했다. Android Studio에서 앱을 시작하려는 전화 가 아직 Android Studio에서 다운로드하지 않은 API 레벨 을 사용하는 경우 가 발생했습니다.

  1. Android Studio를 최신 버전으로 업그레이드
  2. Android Studio 내에서 필요한 API를 다운로드합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.