SDL入门之一 SDL装载,退出,错误信息处理
转自:https://blog.csdn.net/lf426/article/details/2086634及后续文章
1.1:SDL是什么?
SDL是Simple DirectMedia Layer(简易直控媒体层)的缩写。它是一个跨平台的多媒体库,以用于直接控制底层的多媒体硬件的接口。这些多媒体功能包括了音频、键盘和鼠标(事件)、游戏摇杆等。当然,最为重要的是提供了2D图形帧缓冲(framebuffer)的接口,以及为OpenGL与各种操作系统之间提供了统一的标准接口以实现3D图形。从这些属性我们可以看出,SDL基本上可以认为是为以电脑游戏为核心开发的多媒体库。
SDL支持主流的操作系统,包括Windows和Linux。在官方的介绍中,我们可以找到它所支持的其他平台。(SDL supports Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX. )。SDL本身从C语言开发,并且能很好的在C++等高级语言中使用。在官方可以看到SDL所支持的语言很多。(Including Ada, C#, Eiffel, Erlang, Euphoria, Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP, Pike, Pliant, Python, Ruby, Smalltalk, and Tcl. )
SDL在GNU LGPL version 2下发布,这意味着你可以免费的使用。并且可以免费的用于商业软件的制作(只要你直接使用SDL的动态链接库,Windows下的SDL.dll)。如果你将SDL库编译进了自己的二进制代码中,你需要指明你所使用的SDL库的版本以及包括你自己修改的源代码,并说明这些代码的原始出处。这是很宽松的法律,你可以用如此强大的多媒体库完全合法的免费开发商业游戏。
1.2 下载源码
http://www.libsdl.org/download-2.0.php
1.3 SDL的装载,位标(flags)
第一个SDL函数是:int SDL_Init(Uint32 flags);
它的返回值是int,这个我们很熟悉。如果SDL成功初始化装载,函数返回0,如果异常,则返回-1
Uint32 是什么?
SDL使用了一个简单的约定:U就是unsigned(无符号,意味着非负)的意思,与之对应的S代表signed(有符号,可正可负);
int还是整数的意思;32表示占32位,类似的,还可以占1至4个字节,即8,16,32,64位。Uint32的意思就是无符号的,占32位的整数类。
flags是什么意思?
在计算机里,通常把flag叫做位标——其实,bit flag才是位标,不过这种用法貌似已经是一种习惯。所以,从flags字面,我们至少可以理解到三层含义
1) 关键字“位”,这意味着我们需要用二进制的观点看这个值,并且,这个值可以参与位运算;
2) 关键字“标”,这显然是标记的意思。小狗通常采用一些不文明的手段表明某个区域是自己的势力范围,而人类则通常采用插一面代表自己势力的旗帜,所以这就是flag的本意。
3) 关键字"s",这里使用了复数,表明我们可以不止插一面旗。
函数的位标的定义:(就在SDL.h文件中)
#define SDL_INIT_TIMER 0x00000001
#define SDL_INIT_AUDIO 0x00000010
#define SDL_INIT_VIDEO 0x00000020
#define SDL_INIT_CDROM 0x00000100
#define SDL_INIT_JOYSTICK 0x00000200
#define SDL_INIT_EVERYTHING 0x0000FFFF
SDL_WasInit?
第二个函数 int SDL_WasInit(Uint32 flags);
官方文档里面举了3个例子,后面我将举一个我个人觉得比较直观的程序例子。
/* Get init data on all the subsystems */
Uint32 subsystem_init;
subsystem_init=SDL_WasInit(SDL_INIT_EVERYTHING);
if(subsystem_init&SDL_INIT_VIDEO)
printf("Video is initialized./n");
else
printf("Video is not initialized./n");
/* Check for two subsystems */
Uint32 subsystem_mask=SDL_INIT_VIDEO|SDL_INIT_AUDIO;
if(SDL_WasInit(subsystem_mask)==subsystem_mask)
printf("Video and Audio initialized./n");
else
printf("Video and Audio not initialized./n");
1.4 第三个函数SDL的退出函数,其原形是:void SDL_Quit(void);
通常,我们在可以预测程序结束的时候直接使用语句:SDL_Quit();
更多的时候,以及SDL官方文档里面,也推荐使用:atexit(SDL_Quit);
一个安全退出SDL的函数如下:
void endSDL(){
if ( SDL_WasInit(SDL_INIT_EVERYTHING) == 0 ) {
std::cout << "SDL was NOT running!/n";
return;
}
SDL_Quit();
std::cout << "SDL_Quit successfully./n";
return;
}
下面是完整测试程序:
test.h
#include <iostream>
#include "SDL/SDL.h"
void beginSDL();
void endSDL();
test.cpp
#include "test.h"
void beginSDL(){
if ( SDL_WasInit(SDL_INIT_EVERYTHING) != 0 ) {
std::cout << "SDL is already running./n";
return;
}
if ( SDL_Init(SDL_INIT_EVERYTHING) == -1 ) {
throw "Unable to init SDL!";
}
std::cout << "SDL is running successfully./n";
return;
}
void endSDL(){
if ( SDL_WasInit(SDL_INIT_EVERYTHING) == 0 ) {
std::cout << "SDL was NOT running!/n";
return;
}
SDL_Quit();
std::cout << "SDL_Quit successfully./n";
return;
}
#include "test.h"
int main(int argc, char* argv[]){
try {
beginSDL();
}
catch ( const char* s ) {
std::cout << s << std::endl;
return -1;
}
std::cout << SDL_WasInit(SDL_INIT_EVERYTHING) << std::endl;
atexit(endSDL);
return 0;
}
1.5 中途装载与退出
如果我们在程序一开始只启动了video,在运行的某个期间需要启动audio,之后,又需要关掉video只保持audio听声音应该怎么做呢?
先说中途装载。我们首先想到的,还是通过SDL_Init();来装载audio。这看似合理的,而且通过本人试验,发现事实上也是可行的。
但是,我们前面分析过一个逻辑,就是一个程序最好只装载一次Init,这样更容易看出来SDL是从什么时候开始工作的。
那么,为了表明之后的装载是在SDL某些flags已经装载之后的中途装载,SDL提供了一个基本上类似的函数:
int SDL_InitSubSystem(Uint32 flags);
与Init一样,返回值为0则成功装载,-1则失败。
中途退出某些flags的问题,我们显然就不能用SDL_Quit();了,因为这是所有flags全退。
SDL提供了中途退出某些flags的函数:void SDL_QuitSubSystem(Uint32 flags);
一段演示如何中途装载与中途退出的大致过程:
SDL_Init(SDL_INIT_VIDEO);
SDL_InitSubSystem(SDL_INIT_AUDIO);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
SDL_Quit();
1.6 SDL错误信息
在前面的例子中,我们自己提供了出现异常的错误信息,实际上,SDL也提供了自己的错误信息返回函数:
在官方文档中提供的示范例子是C风格的表述:
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
printf("SDL_Init Failed: %s/n", SDL_GetError());
// Unrecoverable error, exit here.
}
值得注意的是,这个函数的返回值是C风格字符串char* ,当我们使用C++风格的异常处理的时候,如果
throw SDL_GetError();
那么,应该catch一个char*对象
catch ( const char* s ) {
}
当我们并不是很熟悉SDL内置的错误信息的时候,自己写异常信息是更值得推荐的选择。
最后介绍的函数是 void SDL_ClearError(void);
它将清除所有错误信息。这用于清除掉你已经处理过的错误信息——否则即使没有异常,你仍然可能收到上次异常的错误信息。
浙公网安备 33010602011771号