当前位置: 网学 > 编程文档 > Android > 正文

Android原生(Native)C开发之四 SDL移植笔记

来源:Http://myeducs.cn 联系QQ:点击这里给我发消息 作者: myeducs.cn 发布时间: 13/03/17

【网学网提醒】:网学会员为广大网友收集整理了,Android原生(Native)C开发之四 SDL移植笔记,希望对大家有所帮助!


    Android原生(Native)C开发之四:SDL移植笔记
    摘要:因为SDL是用纯C写的一套类库,所以移植性非常好,官方支持的系统有:Linux,Windows,WindowsCE,BeOS,MacOS,MacOSX,FreeBSD,NetBSD,OpenBSD,BSD/OS,Solaris,IRIX,andQNX,非官方支持的有:AmigaOS,Dreamcast,Atari,AIX,OSF/Tru64,RISCOS,SymbianOS,andOS/2,而且网上也有人将SDL移植到很多其他嵌入式系统,甚至有人将SDL移植到MotoA1200,如此强大的可移植性,其架构真是值得好好学习
    -
    SDL(SimpleDirectMediaLayer)是一套开放源码的跨平台多媒体开发库,使用C语言写成。SDL提供了多种图像、声音、键盘等的实现,可配置性与移植性非常高,开发者可以开发出跨多个平台(Linux、Windows、MacOSX、Symbian、WidnowsMobiel等嵌入式系统,当然也包括今天要移植的平台:Android)的应用,目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用。
    
    目前,SDL的稳定版本是1.2.13,1.3还在开发中,可以通过SVN得到最新的代码,本次移植以1.2.13为准,没有测试1.3版的源码。请从SDL的官方网站下载1.2.13的源码,文件名为:SDL-1.2.13.zip,并解压,将得到一个SDL-1.2.13目录。
    
    在Native编译SDL之前,要先装CodeSourcery公司的arm交叉编译器,如果是用Windows操作系统,则一定要装Cygwin(一个在windows上模拟linux的软件),因为在编译时要用到一些linux命令,具体的步骤请参见:PortSDL/TinySDGLtoandroidwithnativeC,或自已在网上搜一些资料
    
    因为SDL是用纯C写的一套类库,所以移植性非常好,官方支持的系统有:Linux,Windows,WindowsCE,BeOS,MacOS,MacOSX,FreeBSD,NetBSD,OpenBSD,BSD/OS,Solaris,IRIX,andQNX,非官方支持的有:AmigaOS,Dreamcast,Atari,AIX,OSF/Tru64,RISCOS,SymbianOS,andOS/2,而且网上也有人将SDL移植到很多其他嵌入式系统,甚至有人将SDL移植到MotoA1200,如此强大的可移植性,其架构真是值得好好学习。
    
    现在切入正题,如何为Android量身定做一个SDL,下面就从视频,音频,输入事件,定时器(video,audio,events[key,mouse],timer),多线程等几个方面来分析:
    1.首先讲视频方面,Android是一个定制的Linux操作系统,Linux显示要么用X11,要么用framebuffer技术,很显然Android并没有集成X11(也许Android的软件界面是基于X11的?!),那只有唯一的选择:framebuffer!
    打开$SDL/src/video目录,可以发现SDL支持多达30多种的视频显示技术,其中包括我们想要的fbcon及directfb,directfb我没有做测试,也许显示效果会比linux自带的fbcon好,有兴趣的朋友可以试一下,成功了别忘了告诉我;
    2.再来谈音频,记得一个广告词:没有声音,再好的戏也出不来!可见音频
    对多媒体应用的重要性。
    这次用的是OSS的driver,但用的是dsp及dma的实现,但在打开Android指定的音频文件/dev/eac时有误,所以音频这一块只是能编译通过,不能正常运行,正在考虑用ALSA(AdvancedLinuxSoundArchitecture)替代;
    关于OSS大家可以参看IBM的文章:OSS--跨平台的音频接口简介,写得比较详细。
    3.输入事件(键盘,鼠标)中的键盘事件不需要任何更改,就能正常处理,用的设备文件是/dev/tty0,
    但鼠标事件却不能正常处理,加上DEBUG_MOUSE发现用的是PS2的鼠标,但其实Android用的不是PS2的鼠标,用的应该是触摸屏(TouchScreen)鼠标,设备文件是/dev/input/event0,详情请参见本人的blog:Android原生(Native)C开发之三:鼠标事件篇(捕鼠记),经过改动后,基本能实现鼠标的处理;
    4.定时器用的是unix的实现;
    5.多线程用的是pthread的实现,unix系统都是用pthread来实现多线程的,在lndemo时别忘了加-lpthread;
    6.加载动态库用的是unix的dl库,同样,在lndemo时别忘了加-ldl。
    
    SDL提供了一个最小化的Makefile:Makefile.minimal,所有的实现都是dummy,就是一个空的实现,编译能通过,但运行时什么都不能做,根据上面的分析,将Makefile.minimal的内容改成如下:
    
    #MakefiletobuildtheSDLlibrary
    INCLUDE=-I./include
    CFLAGS=-g-s-O2$(INCLUDE)
    CC=arm-none-linux-gnueabi-gcc
    AR=arm-none-linux-gnueabi-ar
    RANLIB=arm-none-linux-gnueabi-ranlib
    CONFIG_H=include/SDL_config.h
    TARGET=libSDL.a
    SOURCES=\
    src/*.c\
    src/audio/*.c\
    src/cdrom/*.c\
    src/cpuinfo/*.c\
    src/events/*.c\
    src/file/*.c\
    src/joystick/*.c\
    src/stdlib/*.c\
    src/thread/*.c\
    src/timer/*.c\
    src/video/*.c\
    src/audio/dsp/*.c\
    src/audio/dma/*.c\
    src/video/fbcon/*.c\
    src/joystick/dummy/*.c\
    src/cdrom/dummy/*.c\
    src/thread/pthread/*.c\
    src/timer/unix/*.c\
    src/loadso/dlopen/*.c\
    OBJECTS=$(shellecho$(SOURCES)|sed-e's,\.c,\.o,g')
    all:$(TARGET)
    $(TARGET):$(CONFIG_H)$(OBJECTS)
    $(AR)crv$@$^
    $(RANLIB)$@
    $(CONFIG_H):
    cp$(CONFIG_H).default$(CONFIG_H)
    clean:
    rm-f$(TARGET)$(OBJECTS)
    
    最后将$SDL\include\SDL_config_minimal.h的内容改成如下:
    #ifndef_SDL_config_minimal_h
    #define_SDL_config_minimal_h
    #include"SDL_platform.h"
    
    #include
    typedefsignedcharint8_t;
    typedefunsignedcharuint8_t;
    typedefsignedshortint16_t;
    typedefunsignedshortuint16_t;
    typedefsignedintint32_t;
    typedefunsignedintuint32_t;
    typedefunsignedintsize_t;
    //typedefunsignedlonguintptr_t;
    #defineHAVE_LIBC1
    #ifdefHAVE_LIBC
    
    #defineHAVE_ALLOCA_H1
    #defineHAVE_SYS_TYPES_H1
    #defineHAVE_STDIO_H1
    #defineSTDC_HEADERS1
    #defineHAVE_STDLIB_H1
    #defineHAVE_STDARG_H1
    #defineHAVE_MALLOC_H1
    #defineHAVE_MEMORY_H1
    //#defineHAVE_STRING_H1
    //#defineHAVE_STRINGS_H1
    #defineHAVE_INTTYPES_H1
    #defineHAVE_STDINT_H1
    #defineHAVE_CTYPE_H1
    #defineHAVE_MATH_H1
    //#defineHAVE_ICONV_H1
    #defineHAVE_SIGNAL_H1
    #defineHAVE_ALTIVEC_H1
    
    #defineHAVE_MALLOC1
    #defineHAVE_CALLOC1
    #defineHAVE_REALLOC1
    #defineHAVE_FREE1
    #defineHAVE_ALLOCA1
    #defineHAVE_GETENV1
    #defineHAVE_PUTENV1
    #defineHAVE_UNSETENV1
    #defineHAVE_QSORT1
    #defineHAVE_ABS1
    //#defineHAVE_BCOPY1
    //#defineHAVE_MEMSET1
    //#defineHAVE_MEMCPY1
    //#defineHAVE_MEMMOVE1
    //#defineHAVE_MEMCMP1
    //#defineHAVE_STRLEN1
    //#defineHAVE_STRLCPY1
    //#defineHAVE_STRLCAT1
    //#defineHAVE_STRDUP1
    #defineHAVE__STRREV1
    #defineHAVE__STRUPR1
    #defineHAVE__STRLWR1
    //#defineHAVE_INDEX1
    #defineHAVE_RINDEX1
    //#defineHAVE_STRCHR1
    #defineHAVE_STRRCHR1
    #defineHAVE_STRSTR1
    #defineHAVE_ITOA1
    #defineHAVE__LTOA1
    #defineHAVE__UITOA1
    #defineHAVE__ULTOA1
    #defineHAVE_STRTOL1
    #defineHAVE_STRTOUL1
    #defineHAVE__I64TOA1
    #defineHAVE__UI64TOA1
    #defineHAVE_STRTOLL1
    #defineHAVE_STRTOULL1
    #defineHAVE_STRTOD1
    #defineHAVE_ATOI1
    #defineHAVE_ATOF1
    #defineHAVE_STRCMP1
    #defineHAVE_STRNCMP1
    #defineHAVE__STRICMP1
    #defineHAVE_STRCASECMP1
    #defineHAVE__STRNICMP1
    #defineHAVE_STRNCASECMP1
    #defineHAVE_SSCANF1
    #defineHAVE_SNPRINTF1
    #defineHAVE_VSNPRINTF1
    //#defineHAVE_ICONV
    #defineHAVE_SIGACTION1
    #defineHAVE_SETJMP1
    #defineHAVE_NANOSLEEP1
    //#defineHAVE_CLOCK_GETTIME1
    #defineHAVE_DLVSYM1
    #defineHAVE_GETPAGESIZE1
    #defineHAVE_MPROTECT1
    #else
    
    #include
    #endif
    //#defineHAVE_STDIO_H1
    //#defineHAVE_STDINT_H1
    //#defineSDL_INPUT_TSLIB1//touchscreeninput
    #defineSDL_AUDIO_DRIVER_OSS1//SDL_AUDIO_DRIVER_DUMMY
    #defineSDL_CDROM_DISABLED1
    #defineSDL_JOYSTICK_DISABLED1
    #defineSDL_LOADSO_DLOPEN1
    //SDL_LOADSO_DISABLED1//#undef
    #defineSDL_THREAD_PTHREAD1//SDL_THREADS_DISABLED
    //SDL_TIMERS_DISABLED
    #defineSDL_TIMER_UNIX1
    //SDL_VIDEO_DRIVER_DUMMY
    #defineSDL_VIDEO_DRIVER_FBCON1
    #endif
    
    
    
    注意黑体部分,其实就是打开一些宏定义,将SDL的实现一一打开。
    改完了这些以后,还需要改一些代码,主要是video方面的,因为AndroidLinux的framebuffer设备文件与标准Linux不同,Linux的fb设备文件一般是/dev/fb0,但Android的设备文件是/dev/graphics/fb0,打开$SDL/src/video/fbcon/SDL_fbvideo.c,将191、499行的"/dev/fb0"替换成"/dev/graphics/fb0",保存即可。
    再修改$SDL/src/thread/pthread/SDL_sysmutex.c,将第30行改成:#defineFAKE_RECURSIVE_MUTEX1,就是在后面加一个“1”子,这可能是编译器的一个bug,define默认应
    该就是“1”的。
    现在可以开始编译libSDL.a了,在cygwin或Linux下,进入SDL目录,输入:
    make-fMakefile.minimal
    视情况面定,一般几分钟后能顺利编译Android版的SDL,编译成功后,就需要编译几个SDL的testdemo来测试一下SDL的性能。
    进入test目录,复制Makefile.in文件,并改名为Makefile,将前面一点内容改为:
    
    #MakefiletobuildtheSDLtests
    srcdir=.
    INCLUDE=-I../include
    CC=arm-none-linux-gnueabi-gcc
    EXE=
    CFLAGS=-g-s-O2$(INCLUDE)-static
    LIBS=-L..-lSDL-lpthread
    MATHLIB=-lm
    
    
    并将所有的@MATHLIB@替换成$(MATHLIB),保存后,先编译一个testspritedemo,在命令行输入:
    maketestsprite
    编译成功后,启动Android模拟器,将编译出来的testsprite及icon.bmp上传至一个目录,如/dev/sample,命令如下:
    
    adbpushtestspirte/dev/sample/testsprite
    adbpushicon.bmp/dev/sample/icon.bmp
    
    
    最后进入android的shell:adbshell,再进入/dev/sample目录,执行testspritedemo即可:
    
    #cd/dev/sample
    #chmod755testsprite
    #./testsprite-width320-height480-bpp32
    
    
    可以根据模拟器的设置调整width及height,因为程序默认的是640x480的,初始化时会失败,如果一切正常的话,模拟器就会出现很多黄色的笑脸!按任意键退出,在本人机器上能达到60FPS左右,效果图如下:
    其他的demo有兴趣的朋友可以自己编译测试。
    
  • 上一篇资讯: Android发展
  • 下一篇资讯: android单位
  • 网学推荐

    免费论文

    原创论文

    浏览:
    设为首页 | 加入收藏 | 论文首页 | 论文专题 | 设计下载 | 网学软件 | 论文模板 | 论文资源 | 程序设计 | 关于网学 | 站内搜索 | 网学留言 | 友情链接 | 资料中心
    版权所有 QQ:3710167 邮箱:3710167@qq.com 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2015 myeducs.Cn www.myeducs.Cn All Rights Reserved
    湘ICP备09003080号