【问题标题】:Android NDK Native Function Call IssueAndroid NDK 原生函数调用问题
【发布时间】:2012-07-06 00:34:52
【问题描述】:

我正在尝试编写一个使用 GNU 科学库 (GSL) 的 Android 应用程序。特别是,我对“libgslcblas.so”的 BLAS 实现感兴趣。我决定利用 Android NDK 编写一个 Java 程序来加载库并进行适当的函数调用。

为了测试它是如何工作的,我尝试编写一个简单的程序来加载“libm.so”并进行任意函数调用。这似乎是我能想到的一个微不足道的 NDK 用例,但我遇到了以下问题:

07-05 18:11:07.264: I/System.out(1298): debugger has settled (1464)
07-05 18:11:07.583: D/dalvikvm(1298): No JNI_OnLoad found in /system/lib/libm.so 0x41345988, skipping init
07-05 18:11:07.903: W/dalvikvm(1298): No implementation found for native Lissm/libctest/LibCtest;.sqrt (D)D

我的代码如下:

package issm.libctest;

import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;

public class LibCtest extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        TextView  tv = new TextView(this);
        setContentView(R.layout.activity_lib_ctest);

        double x = sqrt(4);

        tv.setText( "Sine of: " + x);
        setContentView(tv);
    }

    public native double sqrt(double x);

    static
    {
        System.load("/system/lib/libm.so");
    }
}

我真的不明白这个问题。正如我所说,这是我能想到的最简单的 NDK 用法。有人可以帮我解决这个问题吗?

谢谢!

【问题讨论】:

  • 您将需要使用JNI 来调用您已使用 NDK 重新编译的本机函数。
  • @KeithFlower 对相关库的引用为零...
  • 是的。我说的是他的全球目标,我认为它是在 GSL 中调用函数,而不是他使用 libm.so 进行的测试(这行不通)。
  • @t0mm13b 他正在尝试使用第三方库,当然不会尝试找到数字的平方根。他试图使用“libgslcblas”的库可能不是为 arm-eabi 构建的。加载“libm”可能是拼写错误或不正确;
  • 我认为用户试图通过在libm.so 中调用sqrt() 来测试他对调用本机函数如何工作的理解。我的评论是关于他的总体目标,我相信(如您所述)需要为 arm-eabi 重新编译 GSL,然后通过 JNI 调用所需的函数。

标签: android android-ndk native


【解决方案1】:

阅读 JNI。简而言之,不能通过 NDK 从 Java 调用任意全局 C 函数。为了可调用,函数需要一个非常具体的签名,大致如下:

void Java_com_mypackage_MyClass_MyMethod(JNIEnv *jni, jobject thiz, jint arg1);

在 Java 方面,这将是包 com.mypackage 中类 MyClass 的方法:

native void MyMethod(int arg1);

显然,香草sqrt 不符合要求。因此,您需要为打算从 Java 调用的每个函数提供一个 Java 友好的包装器。考虑到这一点,您可能希望为仅是数学原语的高级概念提供包装器。 Java/C 边框凌乱;你越少越少越好。

此外,该库需要从专门针对 Android 的源构建。 NDK 有这方面的工具。用于其他平台(例如 Linux 或 Windows)的现成二进制文件将无法使用。

编辑:来自 JDK 的 javah 工具可以采用带有一堆 native 声明的 Java 类,并使用虚拟实现制作骨架 H/C 文件。本质上,是按照 JNI 规则将方法原型从 Java 转换为 C。

【讨论】:

  • "Java/C 边界很乱;越少越好。"阿门。
  • 很好的评论,但我的印象是在 C 中的函数声明中,“extern”是隐含的......我有这个错误吗?哦!我没有意识到函数名必须是那个....丑陋的。 :(
  • extern 是隐含的。我在复制粘贴:)
【解决方案2】:

确保您尝试使用的库(及其依赖项)是为目标平台(Android 原生平台)构建的。

【讨论】:

  • 我对你投反对票的原因在于 logcat 中的线索 - “在 /system/lib/libc.so 中找不到 JNI_OnLoad”,libm 与标准 C 库链接。
猜你喜欢
  • 2014-01-17
  • 2012-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多