2012-07-06 174 views
1

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

为了测试这将如何工作,我试图编写一个简单的程序来加载'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最简单的用法。有人可以帮我解决这个问题吗?

谢谢!

+0

您将需要使用[JNI](http://developer.android.com/guide/practices/jni.html)来调用您使用NDK重新编译的本机函数。 – 2012-07-06 00:57:31

+0

@KeithFlower存在问题库中的零引用... – t0mm13b 2012-07-06 01:02:46

+2

是的。我正在谈论他的全球目标,我认为这是在GSL中调用函数,而不是使用libm.so进行测试(这不会奏效)。 – 2012-07-06 01:08:08

回答

5

阅读关于JNI。简而言之,任意的全局C函数不能从Java通过NDK调用。为了调用一个函数,需要一个非常特殊的签名,沿着线:

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

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

native void MyMethod(int arg1); 

显然,香草sqrt将不适合该法案。因此,您需要为您打算从Java调用的每个函数提供一个Java友好的包装器。考虑到这一点,您可能会想要为仅仅数学基元的高级概念提供包装。 Java/C边界很混乱;越少越好,越好。

此外,该库需要专门为Android构建。 NDK有这方面的工具。另一个平台(例如Linux或Windows)的现成二进制文件将不可用。

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

+2

“Java/C边界很混乱,越少越好。”阿门。 – 2012-07-06 01:23:48

+0

很棒的评论,但我的印象是,在C语言的函数声明中,“extern”是隐含的......我有这个错误吗? OH!我没有意识到这个函数的名字需要......丑陋。 :( – Daeden 2012-07-06 01:28:14

+0

'extern'是隐含的,我是复制粘贴:) – 2012-07-06 01:29:53

0

确保您正尝试使用的库(及其依赖项)是针对目标平台(Android Native平台)构建的。

+0

我低估了你的原因是logcat中的线索 - “libm”与标准C库链接的“在/system/lib/libc.so中找不到JNI_OnLoad”。 – t0mm13b 2012-07-06 00:58:10

+1

@ t0mm13b在投票前询问是很好的做法。 – Tatvamasi 2012-07-06 01:18:01