94

我正在尝试将 NDK 与 C++ 一起使用,但似乎无法使方法命名约定正确。我的原生方法如下:

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

带有包含在 extern "C" {} 中的标头。

一切都编译得很好,创建了一个 .so 文件并复制到我的项目下的 libs 文件夹,但是当我在 Eclipse 中调试和运行时,我不断收到一条日志猫消息,即“没有找到本机的实现......”。由于所有 NDK 示例都在 C 中,我有什么遗漏吗?

谢谢。

4

11 回答 11

169

有几件事可能导致“找不到实现”。一个是函数原型名称错误,另一个是根本无法加载 .so。您确定System.loadLibrary()在使用该方法之前正在调用它吗?

如果您没有JNI_OnLoad定义函数,您可能想要创建一个并让它吐出一条日志消息,以验证该库是否已成功拉入。

您已经避开了最常见的问题——忘记使用extern "C"——所以要么是上述问题,要么是一些轻微的拼写错误。Java 声明是什么样的?

于 2010-03-19T21:03:18.083 回答
20

此错误的另一个原因:您未修饰的本机方法名称不得包含下划线!

例如,我想导出一个名为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!
    ...
于 2014-02-07T19:51:37.893 回答
14

我遇到了同样的问题,但对我来说,错误出现在文件 Android.mk 中。我有它:

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

但应该有这个:

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

注意细节+=代替:=

我希望这会有所帮助。

于 2013-05-16T23:40:51.577 回答
6

如自动生成的 Studio 示例中提供的那样调用 extern "C",但忘记将文件的整个其余部分(包括以下函数)包装在 {} 括号中。只有第一个功能有效。

于 2017-07-13T22:44:06.220 回答
4

在ndk的apps下有一个cpp例子: https ://github.com/android/ndk-samples/blob/master/hello-gl2/app/src/main/cpp/gl_code.cpp

于 2010-02-05T01:49:12.840 回答
4

另一个原因:在 android.mk 中使用 LOCAL_WHOLE_STATIC_LIBRARIES 而不是 LOCAL_STATIC_LIBRARIES。这会阻止库优化未使用的 API 调用,因为 NDK 无法检测到 Java 代码中对本机绑定的使用。

于 2013-10-01T18:35:59.903 回答
2

使用 javah(Java SDK 的一部分)。它正是为此而设计的工具(从 .class 文件生成 .h 标头)。

于 2011-08-03T13:07:22.523 回答
2

如果您的包名包含 _ 字符,则应在 _ 字符后写 1(一),如下所示:

MainActivity.java

package com.example.testcpp_2;

本机 lib.cpp

JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(
于 2018-03-09T06:55:07.150 回答
0

我尝试了上述所有解决方案,但没有人能解决我的构建错误(jni java.lang.UnsatisfiedLinkError: No implementation found for...),最后我发现我忘记将我的 verify.cpp 源文件添加到 CMakeList.txt add_library 段(verify.cpp 是通过 Ctrl + Enter 快捷键自动生成的,可能是其他文件名),希望我的回答可以帮助一些人。

我的构建环境:Gradle + CMake

于 2017-08-15T12:30:19.740 回答
0

我遇到了同样的问题,在我的情况下,原因是我在包名称“RFID_Test”中有下划线我重命名了包并且它有效。感谢用户1222021

于 2017-10-19T17:51:54.347 回答
-3

我两次遇到同样的问题。碰巧的是,我尝试从 Android Studio 启动应用程序的手机使用了我尚未在 Android Studio 中下载的API 级别。

  1. 将 Android Studio 升级到最新版本
  2. 从 Android Studio 中下载必要的 API
于 2018-08-29T08:59:47.050 回答