【问题标题】:Android NDK C++ JNI (no implementation found for native...)Android NDK C++ JNI(没有找到原生的实现......)
【发布时间】:2011-01-12 23:07:22
【问题描述】:

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

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

还有一个包含在 extern "C" {} 中的标题。

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

谢谢。

【问题讨论】:

  • 您是否使用javah 生成您的JNI 存根?如果不是,你应该是。 :-P
  • 很可能是因为你没有打电话给System.loadLibrary
  • 感谢您的提问。我今天学到了一个新东西。

标签: android android-ndk


【解决方案1】:

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

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

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

【讨论】:

  • 耶稣!你为我节省了几个小时的工作时间——读完这篇文章后,我才想起我的 loadLibrary 调用被注释掉了......
  • 你也救了我!我四次检查了我的函数名和其他一些东西......但我忘记了 extern "C",甚至没有在问题中注意到它!
  • 还有一种没有人告诉过的情况:你不能在函数名中使用'_'(下划线),因为下划线被解释为包分隔符。所以,只有驼峰式函数名是可能的
  • @Nulik:如果您将escape it 用作“_1”,则可以使用“_”。
【解决方案2】:

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

例如,我想导出一个名为 AudioCapture_Ping() 的 C 函数。这是我在 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!
    ...

【讨论】:

  • Java 语言声明中出现的“_”必须在本机声明中替换为“_1”。见docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/…中的表2-1。
  • 如此明显,但经过几个小时的调试,我还是没能自己弄清楚……谢谢,你救了我!
  • @user1222021 我有一个问题,我们可以为项目中的所有活动导出cpp方法吗,我们需要在.cpp文件中的方法中指定活动名称吗?
【解决方案3】:

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

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

但应该有这个:

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

注意细节 += 而不是 :=

希望对你有帮助。

【讨论】:

  • 或者你可以将它们全部添加到一行,或者使用`\`换行符。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

    • 区别在哪里:“在 android.mk 中使用 LOCAL_WHOLE_STATIC_LIBRARIES 而不是 LOCAL_STATIC_LIBRARIES”
    【解决方案6】:

    【讨论】:

    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

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

      MainActivity.java

      package com.example.testcpp_2;
      

      native-lib.cpp

      JNICALL
      Java_com_example_testcpp_12_MainActivity_stringFromJNI(
      

      【讨论】:

        【解决方案9】:

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

        我的构建环境:Gradle + CMake

        【讨论】:

          【解决方案10】:

          我遇到了同样的问题,就我而言,原因是我在包名称“RFID_Test”中有下划线 我重命名了 Package 并且它起作用了。 谢谢user1222021

          【讨论】:

            【解决方案11】:

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

            1. 将 Android Studio 升级到最新版本
            2. 从 Android Studio 中下载必要的 API

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-05-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多