Android NDK C++ JNI(没有找到本机的实现...)

Pat*_*fka 84 android android-ndk

我正在尝试使用带有C++的NDK,并且似乎无法使方法命名约定正确.我的原生方法如下:

extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
   //
}
}
Run Code Online (Sandbox Code Playgroud)

标题包含在extern"C"{} aslo中.

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

谢谢.

fad*_*den 130

有一些事情可能导致"没有找到实施".一个是使函数原型名称错误,另一个是无法加载.so.你确定System.loadLibrary()在使用该方法之前调用了吗?

如果您没有JNI_OnLoad定义函数,您可能需要创建一个函数并让它发出日志消息,以验证是否已成功引入了lib.

你已经避开了最常见的问题 - 忘了使用extern "C"- 所以它是上面的或者是一些轻微的拼写错误.Java声明是什么样的?

  • 耶稣!你节省了我几个小时的工作 - 在阅读本文时我记得我已经将我的loadLibrary调用注释掉了...... (12认同)
  • 你也救了我!我四倍检查了我的功能名称和其他一些东西......但我忘记了外部的"C",甚至没有注意到它的问题! (11认同)
  • 还有一种情况没有人告诉您:您不能在函数名称中使用'_'(下划线),因为下划线被视为包分隔符。因此,仅驼峰式功能名称是可能的 (2认同)
  • @Nulik:如果[转义](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names)为“ _1”,则可以使用“ _” 。 (2认同)

小智 18

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

例如,我想导出一个名为的C函数AudioCapture_Ping().这是我在C中的出口声明:

JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object);  //Notice the underscore before Ping
Run Code Online (Sandbox Code Playgroud)

这是我的Java类导入函数:

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

在删除下划线之前,我无法让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!
    ...
Run Code Online (Sandbox Code Playgroud)

  • 在Java语言声明中出现'_'必须在本机声明中替换为"_1".请参阅http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html中的表2-1. (5认同)

ade*_*190 13

我有同样的问题,但对我来说错误是在Android.mk文件中.我有它:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp 
Run Code Online (Sandbox Code Playgroud)

但应该这样:

LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp 
Run Code Online (Sandbox Code Playgroud)

注意细节+ =而不是:=

我希望有所帮助.

  • 或者你可以将它们全部添加到一行,或使用`\\`换行符. (2认同)

Dra*_*ord 6

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


小智 5

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

  • 您可以在 android-ndk/samples/hello-gl2 中找到 cpp 文件,它是 Android NDK 发行版的一部分 (2认同)

Joh*_*igg 5

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

  • 区别在哪里:“在 android.mk 中使用 LOCAL_WHOLE_STATIC_LIBRARIES 而不是 LOCAL_STATIC_LIBRARIES” (2认同)