SDL&android

文章链接:http://www.liuschen.com

下载SDL:http://www.libsdl.org/download-2.0.php

1.通过jni编译SDL

解压下载的SDL文件

将目录下的include,src文件夹以及Android.mk文件分别移动到jni目录下,执行ndk-build

我用的版本是2.0.5,编译会出现如下错误:

[armeabi] Compile thumb  : SDL2 <= SDL_render_gles.c
[armeabi] Compile thumb  : SDL2 <= SDL_render_gles2.c
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_gles2funcs.h: In function 'GLES2_LoadFunctions':
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_render_gles2.c:294:45: warning: assignment from incompatible pointer type [enabled by default]
 #define SDL_PROC(ret,func,params) data->func=func;
                                             ^
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_gles2funcs.h:56:1: note: in expansion of macro 'SDL_PROC'
 SDL_PROC(void, glShaderSource, (GLuint, GLsizei, const GLchar* const*, const GLint *))
 ^

具体原因没有分析,但是改用2.0.3后,编译通过(历史下载列表)。

编译出so文件后,又将目录下的AndroidProject中的Activity移动到了项目下(路径名也要一致,因为在c中有映射,改那个太麻烦),运行工程,再次出错

JNI DETECTED ERROR IN APPLICATION: JNI GetStaticMethodID called with pending exception 'java.lang.NoSuchMethodError' thrown in int org.libsdl.app.SDLActivity.nativeInit(java.lang.Object):-2
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]     in call to GetStaticMethodID
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]     from int org.libsdl.app.SDLActivity.nativeInit(java.lang.Object)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] "SDLThread" prio=5 tid=19 Runnable
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   | group="main" sCount=0 dsCount=0 obj=0x12d884c0 self=0xab66f138
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   | sysTid=22530 nice=0 cgrp=default sched=0/0 handle=0xab66f768
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   | state=R schedstat=( 823907 204323 7 ) utm=0 stm=0 core=6 HZ=100
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   | stack=0xe4a25000-0xe4a27000 stackSize=1036KB
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   | held mutexes= "mutator lock"(shared held)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #00 pc 000049f4  /system/lib/libbacktrace_libc++.so (_ZN13UnwindCurrent6UnwindEjP8ucontext+23)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #01 pc 000030cd  /system/lib/libbacktrace_libc++.so (_ZN9Backtrace6UnwindEjP8ucontext+8)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #02 pc 002481c5  /system/lib/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiPKcPNS_6mirror9ArtMethodE+68)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #03 pc 0022bf1d  /system/lib/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+144)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #04 pc 000b0c53  /system/lib/libart.so (_ZN3artL8JniAbortEPKcS1_+582)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #05 pc 000b1389  /system/lib/libart.so (_ZN3art9JniAbortFEPKcS1_z+60)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #06 pc 000b44cb  /system/lib/libart.so (_ZN3art11ScopedCheckC2EP7_JNIEnviPKc+1286)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #07 pc 000b6793  /system/lib/libart.so (_ZN3art8CheckJNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+26)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #08 pc 00042707  /data/app/ketr.com.androidsdl-1/lib/arm/libSDL2.so (SDL_Android_Init+106)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #09 pc 0000116f  /data/app/ketr.com.androidsdl-1/lib/arm/libSDL2main.so (Java_org_libsdl_app_SDLActivity_nativeInit+2)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   native: #10 pc 0002d319  /data/data/ketr.com.androidsdl/cache/slice-slice_5-classes.dex (Java_org_libsdl_app_SDLActivity_nativeInit__Ljava_lang_Object_2+100)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   at org.libsdl.app.SDLActivity.nativeInit(Native method)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   at org.libsdl.app.SDLMain.run(SDLActivity.java:1028)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]   at java.lang.Thread.run(Thread.java:818)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] 
11-08 13:52:18.701 22508-22530/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x1d in tid 22530 (SDLThread)

这个问题是由于jni对java的调用找不到方法导致的,c函数调用Java时,在core/android里面的实现出了问题,里面的函数还用了一些define别名,以及extern C_LINKAGE 来引用一些函数,最后发现调用流程是:

  1. SDLActivity里面调用init的本地方法;
  2. init方法的实现是在main/Android文件夹里SDL_Android_main.c里;
  3. init方法里面调用了core/android里面的方法初始化了,这个初始化的方法调用的是Android的Java代码;
  4. 接着又调用了SDL_main方法,这个方式是main方法的别名define定义的;
  5. 这个main方法就是自己写的主函数

也就是说,SDL最终还是调用的Android里面的方法,就变成了这样:

Android播放器实现(java)——>调用SDL本地方法——>调用java方法——>调用本地引擎方法

有点拐弯抹角,实现起来并不经济,SDL只是为了跨平台而实现的一层框架,并且里面对于Android中Java方法的相互调用,方法名写的比较死,耦合太大,随着版本的升级也要不断改动,如果不需要跨平台,就完全没用。

PS:通过javah生成头文件

app\build\intermediates\classes\debug>javah -jni org.libsdl.app.SDLActivity
错误: 无法访问android.app.Activity
  找不到android.app.Activity的类文件

将目录切换到源文件src目录下执行,能正常生成头文件

Loading Disqus comments...
Table of Contents