2012-07-06 175 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