2011-05-05 71 views
5

我一直在關注如何移植LAME庫和Android NDK的指南。 http://blog.libertadtech.com/2011/02/porting-lame-encoder-to-android-arm.html調用移植庫的本地函數

每一個工作正常我有libmp3lame.so文件。

現在對於第一個測試,我想叫簡單的函數:

void get_lame_version(char *strbuf, size_t buflen, const char *prefix); 

我寫了一個包裝了LAME庫:

package de.goddchen.android.youtubeconverter; 

public class LameWrapper { 

public static native void get_1lame_1version(char[] buf, int len, 
     char[] prefix); 
} 

我這樣稱呼它是這樣的:

public class MainActivity extends Activity { 

static { 
    System.loadLibrary("mp3lame"); 
} 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     char[] buffer = new char[100]; 
     LameWrapper.get_1lame_1version(buffer, 100, "".toCharArray()); 
     ((TextView) findViewById(R.id.text)).setText(buffer.toString()); 
    } 

} 

但我得到以下錯誤:

05-05 10:36:11.973: DEBUG/dalvikvm(199): Trying to load lib /data/data/de.goddchen.android.youtubeconverter/lib/libmp3lame.so 0x43757f78 
05-05 10:36:12.053: DEBUG/dalvikvm(199): Added shared lib /data/data/de.goddchen.android.youtubeconverter/lib/libmp3lame.so 0x43757f78 
05-05 10:36:12.123: DEBUG/dalvikvm(199): No JNI_OnLoad found in /data/data/de.goddchen.android.youtubeconverter/lib/libmp3lame.so 0x43757f78 
05-05 10:36:12.573: DEBUG/dalvikvm(199): +++ not scanning '/system/lib/libwebcore.so' for 'get_1lame_1version' (wrong CL) 
05-05 10:36:12.693: DEBUG/dalvikvm(199): +++ not scanning '/system/lib/libexif.so' for 'get_1lame_1version' (wrong CL) 
05-05 10:36:12.693: DEBUG/dalvikvm(199): +++ not scanning '/system/lib/libFFTEm.so' for 'get_1lame_1version' (wrong CL) 
05-05 10:36:12.703: DEBUG/dalvikvm(199): +++ not scanning '/system/lib/libmedia_jni.so' for 'get_1lame_1version' (wrong CL) 
05-05 10:36:12.703: DEBUG/dalvikvm(199): +++ not scanning '/system/lib/libsrec_jni.so' for 'get_1lame_1version' (wrong CL) 
05-05 10:36:12.703: WARN/dalvikvm(199): No implementation found for native Lde/goddchen/android/youtubeconverter/LameWrapper;.get_1lame_1version ([CI[C)V 
05-05 10:36:12.703: DEBUG/AndroidRuntime(199): Shutting down VM 
05-05 10:36:12.753: INFO/ActivityManager(52): Start proc com.android.alarmclock for broadcast com.android.alarmclock/.AlarmInitReceiver: pid=213 uid=10017 gids={} 
05-05 10:36:12.773: WARN/dalvikvm(199): threadid=3: thread exiting with uncaught exception (group=0x4001aa28) 
05-05 10:36:12.783: ERROR/AndroidRuntime(199): Uncaught handler: thread main exiting due to uncaught exception 
05-05 10:36:12.883: ERROR/AndroidRuntime(199): java.lang.UnsatisfiedLinkError: get_1lame_1version 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at de.goddchen.android.youtubeconverter.LameWrapper.get_1lame_1version(Native Method) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at de.goddchen.android.youtubeconverter.MainActivity.onCreate(MainActivity.java:19) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.ActivityThread.access$2100(ActivityThread.java:116) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.os.Handler.dispatchMessage(Handler.java:99) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.os.Looper.loop(Looper.java:123) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at android.app.ActivityThread.main(ActivityThread.java:4203) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at java.lang.reflect.Method.invoke(Method.java:521) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 
05-05 10:36:12.883: ERROR/AndroidRuntime(199):  at dalvik.system.NativeStart.main(Native Method) 

有人可以請我指出正確的方式來調用libmp3lame.so的功能嗎?

+0

也許需要加個字最後? public static native get_1lame_1version(char [] buf,int len,final char [] prefix); – Pasha 2011-05-05 10:54:16

+0

nope,不起作用:( – Goddchen 2011-05-05 10:58:45

+0

看看這個:http://groups.google.com/group/android-ndk/browse_thread/thread/186678942625f46a/557bfe20de389d24 – Pasha 2011-05-05 11:05:30

回答

5

不幸的是,你不能從Java調用任何舊的C函數。您必須使用具有「損壞」名稱的函數或使用JNI_OnLoad機制。無論哪種方式,Dalvik虛擬機都會爲函數調用添加額外的參數,這是常規的蹩腳的get_version_number函數不期望的。

這個example of using JNI解釋了這個名字mangling。對於您的Java類,您需要具有此原型的函數:

void Java_de_goddchen_android_youtubeconverter_LameWrapper_get_11lame_11version 
    (JNIEnv *, jclass, jcharArray, jint, jcharArray); 

JNIEnv和jclass參數是調用接口的一部分。如果您使用的是C++,請記得指定extern "C"。 javah工具將爲您生成正確的頭文件。

如果我這樣做,我可能會編寫JNI C包裝函數爲我需要的跛腳電話。在這種特殊情況下,我沒有使用帶有長度參數的char *,而是將空char *作爲最後一個參數,我創建了一個更簡單的Java to C接口,它只返回了Java String。所以在Java中:

package de.goddchen.android.youtubeconverter; 

public class LameWrapper { 
    public static native String getVersion(); 
} 

然後在C,其中調用實際跛腳API:

JNIEXPORT jstring JNICALL Java_de_goddchen_android_youtubeconverter_LameWrapper_getVersion 
    (JNIEnv * env, jclass c) 
{ 
    char buffer[80]; 
    get_lame_version(buffer, sizeof(buffer) - 1, ""); 
    return (*env)->NewStringUTF(env, buffer)); 
} 

在這裏創建,然後在Java/Dalvik的側控制的新String的生命週期。