00000029.htm

来自「水木社区 embeded 版精华区 下载」· HTM 代码 · 共 256 行 · 第 1/2 页

HTM
256
字号
<?xml version="1.0" encoding="gb2312"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"/><title>Microsoft Windows CE 编程的十点忠告    turbolinux </title></head><body><center><h1>BBS 水木清华站∶精华区</h1></center><a name="top"></a>发信人:&nbsp;encarta&nbsp;(知更鸟),&nbsp;信区:&nbsp;Embedded&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />标&nbsp;&nbsp;题:&nbsp;Microsoft&nbsp;Windows&nbsp;CE&nbsp;编程的十点忠告&nbsp;<br />发信站:&nbsp;BBS&nbsp;水木清华站&nbsp;(Thu&nbsp;Aug&nbsp;10&nbsp;21:37:50&nbsp;2000)&nbsp;<br />&nbsp;<br />以下转载自微软网站&nbsp;<br />&nbsp;<br />&nbsp;<br />Microsoft&nbsp;Windows&nbsp;CE&nbsp;编程的十点忠告&nbsp;<br />----------------------------------------------------------------------------&nbsp;<br />----&nbsp;<br />  最近两周我们花了大部分时间将已有的应用程序移植到Microsoft&nbsp;Windows&nbsp;CE中。&nbsp;<br />一般说来,这个计划不是太难。我们起步于Microsoft&nbsp;Win32代码,当然&nbsp;Windows&nbsp;CE是&nbsp;<br />基于Win32应用程序接口(API)的。有利的是,我们的应用程序(即Raima&nbsp;数据管理器&nbsp;<br />)有方便的使用接口,并包含一个大约由150个子函数组成的库,这些函数都是由C语言&nbsp;<br />写成,可以用来创建、管理和访问数据库。&nbsp;<br />  按建立应用程序的方式来说,我们原以为将它移植到Windows&nbsp;CE中是一项相对简单&nbsp;<br />的C语言编程练习。然而,我们不久便遇到好些困难。从粗心大意的错误开始,比如在基&nbsp;<br />于Windows&nbsp;NT&nbsp;的Windows&nbsp;CE仿真器上使用Microsoft&nbsp;Windows&nbsp;NT库,接着又违背Windo&nbsp;<br />ws&nbsp;CE的编程戒律,如&quot;千万不要给Unicode(国际标准组织10646标准)字符分配奇数内&nbsp;<br />存地址&quot;。&nbsp;<br />  大约有百分之九十的问题或多或少地与Unicode有关。尽管Unicode编程不难,但是&nbsp;<br />,当给单字节字符编写代码时,很容易出错(我有过许多次错误)。&nbsp;<br />  下面这些忠告是根据我们在Windows&nbsp;CE上编写Raima&nbsp;数据管理器的经验总结出来的&nbsp;<br />,但我相信,在做任何其它Windows&nbsp;CE程序之前,它们都值得借鉴。毕竟大多数Window&nbsp;<br />s开发者,当他们创建第一个Windows&nbsp;CE应用程序时,真正运用的是已掌握的Win32知识&nbsp;<br />。&nbsp;<br />1.&nbsp;不要在仿真器上使用Windows&nbsp;NT库&nbsp;<br />  这里所讨论的第一个错误实在太愚蠢了,但我还是陷了进去,也许你也会。当用Mi&nbsp;<br />crosoft&nbsp;VC++(5.0版)创建一个Windows&nbsp;CE程序时,你会发现,包含路径(include)&nbsp;<br />、&nbsp;库路径(library)、及可执行程序路径被自动调整以匹配反应目标环境的选择。因&nbsp;<br />此,比如说为Windows&nbsp;CE模拟器建立应用程序时,你会发现,include路径没有指向Win&nbsp;<br />32的包含文件(在VC目录下),而是指向Windows&nbsp;CE包含文件(在WCE目录下)。千万别&nbsp;<br />去修改。&nbsp;<br />  由于Windows&nbsp;CE在Windows&nbsp;NT下运行,所以仿真器上运行的程序能够调用任一Wind&nbsp;<br />ows&nbsp;NT动态链接库(DLL)中的函数,即使这个DLL不是模拟器的成员也一样。显然,这不&nbsp;<br />是很好的事,因为相同的函数也许在手持PC(H/PC)或Windows&nbsp;CE设备上不可用,而你的&nbsp;<br />软件最终要能在这些设备上运行。&nbsp;<br />  第一次将非Unicode应用程序装入Windows&nbsp;CE仿真器时,你会发现,许多正在使用的&nbsp;<br />函数它都不支持,例如美国国家标准协会(ANSI)定义的字符函数strcpy()。这也许引诱&nbsp;<br />你去链接Windows&nbsp;NT&nbsp;运行时间库,以便能解决所有问题。&nbsp;<br />  如果你是刚开始用Windows&nbsp;CE编程,可能你能用的包含文件和库文件是明显的。答&nbsp;<br />案就是,你不要采用那些在写普通Win32或非Windows&nbsp;CE程序时使用的包含文件和库文件&nbsp;<br />。&nbsp;<br />2.&nbsp;不要混淆TCHARs和bytes&nbsp;<br />  如果你正在Windows&nbsp;CE上写非Unicode应用程序,你或许要将所有的字符串从单个字&nbsp;<br />符(chars)转换为宽字符(widechars)(例如,C变量类型whcar_t)。几乎所有Windows&nbsp;&nbsp;<br />CE支持的Win32和运行时间库函数都要求宽字符变量。Windows&nbsp;95不支持Unicode,然而&nbsp;<br />,为了使程序代码具有可移植性,你要尽可能采用tchar.h中定义的TCHAR类型,不要直&nbsp;<br />接使用wchar_t。&nbsp;<br />  TCHAR是定义为wchar_t还是char,取决于预处理器的符号UNICODE是否定义。同样,&nbsp;<br />所有有关字符串处理函数的宏,如_tcsncpy宏,它是定义为Unicode函数wcsncpy还是定&nbsp;<br />义为ANSI函数strncpy,取决于UNICODE是否定义。&nbsp;<br />  在现存的Windows应用程序中,有些代码也许暗示字符长为单字节。这在给字符串分&nbsp;<br />配内存时经常用到,例如:&nbsp;<br />int&nbsp;myfunc(char&nbsp;*p)&nbsp;<br />{&nbsp;<br />char&nbsp;*pszFileName;&nbsp;<br />pszFileName&nbsp;=&nbsp;malloc(MAXFILELEN);&nbsp;<br />if(pszFileName)&nbsp;<br />strncpy(pszFileName,&nbsp;p,&nbsp;MAXFILELEN);&nbsp;<br />/*etc*/&nbsp;<br />  在这段代码中,分配的内存块应该写作(MAXFILELEN&nbsp;*&nbsp;sizeof(char)),但是大多数&nbsp;<br />程序员喜欢将它简化为MAXFILELEN,因为对于所有的平台来说sizeof(char)的值等于1。&nbsp;<br />然而,当你用TCHARS代替多个字符时,很容易忘记这种固有的概念,于是将代码编写成&nbsp;<br />下面的形式:&nbsp;<br />int&nbsp;myfunc(TCHAR&nbsp;*p)&nbsp;<br />{&nbsp;<br />TCHAR&nbsp;*pszFileName;&nbsp;<br />PszFileName&nbsp;=&nbsp;(TCHAR*)malloc(MAXFILELEN);&nbsp;<br />If&nbsp;(pszFileName)&nbsp;<br />tcsncpy(pszFileName,&nbsp;p,&nbsp;MAXFILELEN);&nbsp;<br />/*etc*/&nbsp;<br />  这是不行的。它马上会导致出错。这里的错误在于malloc函数中指定变量大小为by&nbsp;<br />tes,然而_tcsncpy函数中使用的第三个变量却指定为TCHARs而不是bytes。当UNICODE被&nbsp;<br />定义时,一个TCHAR等于两个字节数(bytes)。&nbsp;<br />上述代码段应该改写为:&nbsp;<br />int&nbsp;myfunc(TCHAR&nbsp;*p)&nbsp;<br />{&nbsp;<br />TCHAR&nbsp;*pszFileName;&nbsp;<br />PszFileName&nbsp;=&nbsp;(TCHAR*)malloc(MAXFILELEN&nbsp;*&nbsp;sizeof(TCHAR));&nbsp;<br />if(pszFileName)&nbsp;<br />tcsncpy(pszFileName,&nbsp;p,&nbsp;MAXFILELEN);&nbsp;<br />/*etc*/&nbsp;<br />3.&nbsp;不要将Unicode&nbsp;字符串放入奇数内存地址&nbsp;<br />  在Intel系列处理器上,你可以在一奇数内存地址储存任何变量或数组,不会导致任&nbsp;<br />何致命的错误影响。但在H/PC上,这一点不一定能行&nbsp;?&nbsp;你必须对大于一个字节的数据类&nbsp;<br />型小心谨慎,包括定义为无符号短型(unsigned&nbsp;short)&nbsp;的wchar_t。当你设法访问它&nbsp;<br />们的时候,将它们置于奇地址会导致溢出。&nbsp;<br />  编辑器经常在这些问题上提醒你。你无法管理堆栈变量地址,并且编辑器会检查确&nbsp;<br />定这些地址与变量类型是否相匹配。同样,运行时间库必须保证从堆中分配的内存总是&nbsp;<br />满足一个word边界&nbsp;,所以你一般不必担心那两点。但是,如果应用程序含有用memcpy(&nbsp;<br />)函数拷贝内存区域的代码,或者使用了某种类型的指针算术以确定内存地址,问题也许&nbsp;<br />就出现了。考虑下面的例子:&nbsp;<br />int&nbsp;send_name&nbsp;(TCHAR&nbsp;*&nbsp;pszName)&nbsp;<br />{&nbsp;<br />char&nbsp;*p,&nbsp;*q;&nbsp;<br />int&nbsp;nLen=(_tcslen(pszName)&nbsp;+&nbsp;1)&nbsp;*&nbsp;sizeof(TCHAR);&nbsp;<br />p=maloc(HEADER_SIZE&nbsp;+&nbsp;nLen);&nbsp;<br />if(p)&nbsp;<br />{&nbsp;<br />q&nbsp;=&nbsp;p&nbsp;+&nbsp;HEADER_SIZE;&nbsp;<br />_tcscpy((TCHAR*)q,&nbsp;pszName);&nbsp;<br />}&nbsp;<br />/*&nbsp;etc&nbsp;*/&nbsp;<br />  这段代码是从堆中分配内存并复制一个字符串,在字符串的开头留一个HEADER_SIZ&nbsp;<br />E的大小。假设UNICODE定义了,那么该字符串就是一个widechar字符串。如果HEADER_S&nbsp;<br />IZE是一个偶数,这段代码就会正常工作,但如果HEADER_SIZE为奇数,这段代码就会出&nbsp;<br />错,因为q指向的地址也将为奇数。&nbsp;<br />  注意,当你在Intel系列处理器中的Windows&nbsp;CE仿真器上测试这段代码时,这个问题&nbsp;<br />是不会发生的。&nbsp;<br />  在这个例子中,只要确保HEADER_SIZE为偶数,你就可以避免问题的发生。然而,在&nbsp;<br />某些情况下你也许不能这么做。例如,如果程序是从一台式PC输入数据,你也许不得不&nbsp;<br />采用事先定义过的二进制格式,尽管它对H/PC不适合。在这种情况下,你必须采用函数&nbsp;<br />,这些函数用字符指针控制字符串而不是TCHAR指针。如果你知道字符串的长度,就可以&nbsp;<br />用memcpy()复制字符串。因此,采用逐个字节分析Unicode字符串的函数也许足以确定字&nbsp;<br />符串在widechars中的长度。&nbsp;<br />4.&nbsp;在ANSI和Unicode字符串之间进行翻译&nbsp;<br />  如果你的Windows&nbsp;CE应用程序接口于台式PC,也许你必须操作PC机中的ANSI字符串&nbsp;<br />

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?