SDL2.0例子代码分析---代码运行平台检测

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2017-12-18 17:41:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
简介SDL2.0例子程序中的 testplatform项目代码分析 ,针对不同的平台 检测字节序 CPU支持的指令集 类型宽度 以及断言

代码+注释
  1. #include <stdio.h>

  2. #include "SDL.h"
  3. #include "SDL_endian.h"
  4. #include "SDL_cpuinfo.h"
  5. #include "SDL_assert.h"

  6. /*
  7. *  该例子代码检测运行平台
  8. */
  9. //判断变量占用字节数 是否等于 hardcodetype
  10. static int
  11. badsize(size_t sizeoftype, size_t hardcodetype)
  12. {
  13.         return sizeoftype != hardcodetype;
  14. }


  15. //检测系统是否出现错误类型   貌似用处不大这段坑爹代码
  16. //如果平台类型错误 返回1 否则返回  0
  17. int
  18. TestTypes(SDL_bool verbose)
  19. {
  20.         int error = 0;

  21.         //如果Uint8占用一个字节
  22.         if (badsize(sizeof(Uint8), 1))
  23.         {
  24.                 //如果Uint8不等于1那么输出 实际占用尺寸
  25.                 if (verbose)
  26.                         SDL_Log("sizeof(Uint8) != 1, instead = %u\n",
  27.                         (unsigned int)sizeof(Uint8));
  28.                 //错误次数++
  29.                 ++error;
  30.         }
  31.         //如如下类似 上述
  32.         if (badsize(sizeof(Uint16), 2)) {
  33.                 if (verbose)
  34.                         SDL_Log("sizeof(Uint16) != 2, instead = %u\n",
  35.                         (unsigned int)sizeof(Uint16));
  36.                 ++error;
  37.         }
  38.         if (badsize(sizeof(Uint32), 4)) {
  39.                 if (verbose)
  40.                         SDL_Log("sizeof(Uint32) != 4, instead = %u\n",
  41.                         (unsigned int)sizeof(Uint32));
  42.                 ++error;
  43.         }
  44.         if (badsize(sizeof(Uint64), 8)) {
  45.                 if (verbose)
  46.                         SDL_Log("sizeof(Uint64) != 8, instead = %u\n",
  47.                         (unsigned int)sizeof(Uint64));
  48.                 ++error;
  49.         }
  50.         if (verbose && !error)
  51.                 SDL_Log("All data types are the expected size.\n");

  52.         return (error ? 1 : 0);
  53. }

  54. //测试尾数  也就是机器的字节序  
  55. //windows默认是小端模式
  56. //也就是 低位先存 原因是 堆栈是 由高地址向低地址扩展
  57. int
  58. TestEndian(SDL_bool verbose)
  59. {
  60.         int error = 0;
  61.         Uint16 value = 0x1234;
  62.         int real_byteorder;
  63.         Uint16 value16 = 0xCDAB;
  64.         Uint16 swapped16 = 0xABCD;
  65.         Uint32 value32 = 0xEFBEADDE;
  66.         Uint32 swapped32 = 0xDEADBEEF;
  67.         Uint64 value64, swapped64;

  68.    //定义64位置 也就是 0x00000000EFBEADDE
  69.         value64 = 0xEFBEADDE;
  70.         //右移动32位  也就是四个字节
  71.         value64 <<= 32;
  72.         //将低位置为0xCDAB3412
  73.         value64 |= 0xCDAB3412;
  74.         //如下操作和value64雷同
  75.         swapped64 = 0x1234ABCD;
  76.         swapped64 <<= 32;
  77.         swapped64 |= 0xDEADBEEF;
  78.         //打印机器字节序 是大端模式还是小端模式
  79.         if (verbose) {
  80.                 SDL_Log("Detected a %s endian machine.\n",
  81.                         (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? "little" : "big");
  82.         }
  83.         //我们自己判断字节序 将value转换为 char类型之后 由于数据丢失 变成了0x34 在windows下低位先存
  84.         //所以 左移4位后变成了0x3了  也就是小端口模式
  85.         if ((*((char *)&value) >> 4) == 0x1) {
  86.                 real_byteorder = SDL_BIG_ENDIAN;
  87.         }
  88.         else {
  89.                 real_byteorder = SDL_LIL_ENDIAN;
  90.         }
  91.         //如果我们分析的 真正的字节序不等于 SDL给出的字节序 那么 输出真正的字节序 error++
  92.         if (real_byteorder != SDL_BYTEORDER) {
  93.                 if (verbose) {
  94.                         SDL_Log("Actually a %s endian machine!\n",
  95.                                 (real_byteorder == SDL_LIL_ENDIAN) ? "little" : "big");
  96.                 }
  97.                 ++error;
  98.         }
  99.         //交换字节序 输出
  100.         if (verbose) {
  101.                 SDL_Log("Value 16 = 0x%X, swapped = 0x%X\n", value16,
  102.                         SDL_Swap16(value16));
  103.         }
  104.         //如果交换后的值不等于 0xABCD
  105.         if (SDL_Swap16(value16) != swapped16) {
  106.                 if (verbose) {
  107.                         SDL_Log("16 bit value swapped incorrectly!\n");
  108.                 }
  109.                 ++error;
  110.         }
  111.         //交换32位高度字节序
  112.         if (verbose) {
  113.                 SDL_Log("Value 32 = 0x%X, swapped = 0x%X\n", value32,
  114.                         SDL_Swap32(value32));
  115.         }
  116.         if (SDL_Swap32(value32) != swapped32) {
  117.                 if (verbose) {
  118.                         SDL_Log("32 bit value swapped incorrectly!\n");
  119.                 }
  120.                 ++error;
  121.         }
  122.         if (verbose) {  
  123.                 //如果是微软的编译器 也就是VC下 打印出64位的交换字节序之后的值
  124. #ifdef _MSC_VER
  125.                 SDL_Log("Value 64 = 0x%I64X, swapped = 0x%I64X\n", value64,
  126.                         SDL_Swap64(value64));
  127. #else  
  128.                 //如果是其他编译器 那么  64位置 ULONG 就需要定义为 unsigned long long 来代表 64位无符号 Integer
  129.                 SDL_Log("Value 64 = 0x%llX, swapped = 0x%llX\n",
  130.                         (unsigned long long) value64,
  131.                         (unsigned long long) SDL_Swap64(value64));
  132. #endif
  133.         }
  134.         //判断交换后的值是否等于 0x1234ABCDDEADBEEF;
  135.         if (SDL_Swap64(value64) != swapped64) {
  136.                 if (verbose) {
  137.                         SDL_Log("64 bit value swapped incorrectly!\n");
  138.                 }
  139.                 ++error;
  140.         }
  141.         //返回错误状态
  142.         return (error ? 1 : 0);
  143. }


  144. //检测CPU 的特性
  145. int
  146. TestCPUInfo(SDL_bool verbose)
  147. {  
  148.         if (verbose) {  
  149.                 //打印CPU数量
  150.                 SDL_Log("CPU count: %d\n", SDL_GetCPUCount());
  151.                 //获取CPU Cache LIne的大小 即CPU 一次从主存Copy的内存大小
  152.                 SDL_Log("CPU cache line size: %d\n", SDL_GetCPUCacheLineSize());
  153.         //CPU是否支持RDTSC指令 读取时间标签计数器
  154.                 SDL_Log("RDTSC %s\n", SDL_HasRDTSC() ? "detected" : "not detected");
  155.                 ///cpu 是否支持 Altivec  AltiVec提供了32个128比特向量暂存器,与之相比,SSE和SSE2只提供了8个
  156.                 SDL_Log("AltiVec %s\n", SDL_HasAltiVec() ? "detected" : "not detected");
  157.                 //cpu是否支持 MMX指令
  158.                 SDL_Log("MMX %s\n", SDL_HasMMX() ? "detected" : "not detected");
  159.                 //CPU是否支持SIMD , 由AMD开发的一套SIMD多媒体指令集,支持单精度浮点数的矢量运算,用于增强x86架构的计算机在三维图像处理上的性能
  160.                 SDL_Log("3DNow! %s\n", SDL_Has3DNow() ? "detected" : "not detected");
  161.                 //cpu是否支持SSE
  162.                 SDL_Log("SSE %s\n", SDL_HasSSE() ? "detected" : "not detected");
  163.                 //SSE2是否支持 如下都是判断CPU是否支持一下加速指令集
  164.                 SDL_Log("SSE2 %s\n", SDL_HasSSE2() ? "detected" : "not detected");
  165.                 SDL_Log("SSE3 %s\n", SDL_HasSSE3() ? "detected" : "not detected");
  166.                 SDL_Log("SSE4.1 %s\n", SDL_HasSSE41() ? "detected" : "not detected");
  167.                 SDL_Log("SSE4.2 %s\n", SDL_HasSSE42() ? "detected" : "not detected");
  168.                 SDL_Log("AVX %s\n", SDL_HasAVX() ? "detected" : "not detected");
  169.                 //获取系统RAM大小 也就是内存大小
  170.                 SDL_Log("System RAM %d MB\n", SDL_GetSystemRAM());
  171.         }
  172.         return (0);
  173. }

  174. int
  175. TestAssertions(SDL_bool verbose)
  176. {  
  177.         //sdl断言
  178.         SDL_assert(0);
  179.         SDL_assert_release(1);
  180.         SDL_assert_paranoid(1);
  181.         SDL_assert(0 || 1);
  182.         SDL_assert_release(0 || 1);
  183.         SDL_assert_paranoid(0 || 1);

  184. #if 0   /* enable this to test assertion failures. */
  185.         SDL_assert_release(1 == 2);
  186.         SDL_assert_release(5 < 4);
  187.         SDL_assert_release(0 && "This is a test");
  188. #endif

  189.         {  
  190.                 //获取所有的断言 链表  在调用SDL_GetAssertionReport 之前
  191.                 /************************************************************************/
  192. /*
  193.                         typedef struct SDL_assert_data
  194.                         {
  195.                         int always_ignore;
  196.                         unsigned int trigger_count;
  197.                         const char *condition;
  198.                         const char *filename;
  199.                         int linenum;
  200.                         const char *function;
  201.                         const struct SDL_assert_data *next;
  202.                         } SDL_assert_data;                                                                     */
  203.                 /************************************************************************/
  204.                 const SDL_assert_data *item = SDL_GetAssertionReport();
  205.                 //我们发现就是取出所有的 断言结果 输出
  206.                 while (item) {
  207.                         SDL_Log("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
  208.                                 item->condition, item->function, item->filename,
  209.                                 item->linenum, item->trigger_count,
  210.                                 item->always_ignore ? "yes" : "no");
  211.                         item = item->next;
  212.                 }
  213.         }
  214.         return (0);
  215. }

  216. int
  217. main(int argc, char *argv[])
  218. {
  219.         SDL_bool verbose = SDL_TRUE;
  220.         int status = 0;

  221.         /* 设置特定日志的优先级 这里是应用程序日志  */
  222.         SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
  223.         //如果参数1= -q 那么设置 verbose=faslse
  224.         if (argv[1] && (SDL_strcmp(argv[1], "-q") == 0)) {
  225.                 verbose = SDL_TRUE;
  226.         }
  227.         if (verbose) {
  228.                 SDL_Log("This system is running %s\n", SDL_GetPlatform());
  229.         }
  230.         //测试变量尺寸
  231.         status += TestTypes(verbose);
  232.         //测试尾数  也就是测试机器的字节序
  233.         status += TestEndian(verbose);
  234.         //测试CPU信息
  235.         status += TestCPUInfo(verbose);
  236.         //测试断言
  237.         status += TestAssertions(verbose);

  238.         return status;
  239. }
复制代码

分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表