??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久国产精华液,久久久久无码精品,久久综合鬼色88久久精品综合自在自线噜噜 http://www.shnenglu.com/kuronca/zh-cnWed, 07 May 2025 13:44:12 GMTWed, 07 May 2025 13:44:12 GMT60Q{QWinCE驱动开发问题精华集?/title><link>http://www.shnenglu.com/kuronca/archive/2008/05/09/49332.html</link><dc:creator>零宇</dc:creator><author>零宇</author><pubDate>Fri, 09 May 2008 09:24:00 GMT</pubDate><guid>http://www.shnenglu.com/kuronca/archive/2008/05/09/49332.html</guid><wfw:comment>http://www.shnenglu.com/kuronca/comments/49332.html</wfw:comment><comments>http://www.shnenglu.com/kuronca/archive/2008/05/09/49332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/kuronca/comments/commentRss/49332.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kuronca/services/trackbacks/49332.html</trackback:ping><description><![CDATA[<strong>如何让系l加载自己写的驱动程序?</strong>   <br>两种办法Q?nbsp; <br>1、在[HKEY_LOCAL_MACHINE\Drivers\BuiltIn]下添加注册键?nbsp; <br>2、在应用E序中调用ActivateDeviceEx?nbsp; <br>  <br> <strong>在一些文件中用分h表示注释Q例如下面的内容   <br></strong>; @CESYSGEN IF SERVERS_MODULES_HTTPD  <br>; @CESYSGEN ENDIF  <br>?#8220;CESYSGEN...”前加?#8220;@”Q有没有什么特别的含义Q?nbsp; <br>在WINCE的一些文件中Q用“;”作ؓ(f)注释q在注释文字中用@CESYSGEN作ؓ(f)标记Q后面接条g语句。Cefilter.exe工具负责按照条g来筛选文件内容,所以不要轻易地删除包含@CESYSGEN的注释语句?nbsp; <br>  <br> 通过串口建立ActiveSync联接,串口U用三线的可以吗?   <br>不可以,因ؓ(f)用串口同步时要用到其余口的状态?nbsp; <br><br>   <br> <strong>    WINCE是否支持MAPIQ?/strong>  <br>不支持。WINCE自带的pmail.exe软g也不是很好用。徏议自开发邮件收发Y件。如果需要购买WINCE下邮件收发Y件可以联pL?nbsp; <br>  <br> <strong>如何旋{屏幕昄的内容?</strong>  <br>例子代码如下Q前提是昄驱动E序支持旋{Q:(x)  <br>DEVMODE  devmode = {0};  <br> devmode.dmSize = sizeof(DEVMODE);  <br> devmode.dmDisplayOrientation = DMDO_90;       ///垂直模式  <br> devmode.dmFields = DM_DISPLAYORIENTATION;  <br> ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL);  ///改变昄的设|?nbsp; <br> CRect  rcWorkArea(0, 0, 320, 240);    ///整个屏幕寸  <br> ///讄客户区大ƈq播消息Q这h有Y件也随之更Ҏ(gu)C?nbsp; <br> SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);   <br>  <br><strong> 请问如何修改字Ş~存的容量?  <br></strong>[HKEY_LOCAL_MACHINE\System\GDI\GLYPHCACHE]  <br>"limit"=dword:0400  <br>  <br><strong> 如何得到从WINCE启动开始到现在的时_(d)</strong>  <br>调用API GetTickCountQ得到的gؓ(f)32位整敎ͼ单位为毫U?nbsp; <br><strong>  <br> 如何调用WINCE的Y键盘Q?/strong>  <br>调用API SipShowIM(SIPF_ON)Q前提是内核加入?jin)Y键盘lg?nbsp; <br>  <br><strong> ZHIVE的注册表Q如何在pȝ关闭前保存注册表的数据到文gsystem.hvQ?/strong>  <br>调用API RegFlushKey函数?nbsp; <br>  <br><strong> 使用VirtualAlloc和VirtualCopy的时候需要注意哪些事?</strong>  <br>1、VirtualAlloc的作用是甌虚拟地址I间Q这肯定不是最l的目的Q最l目的可能是甌物理内存、映寄存器、提交文件等。没有一个目的会(x)在意虚拟地址I间的位|,所以尽量传递参??Q也是让WINCE自动分配虚拟地址I间。VirtualAlloc分配地址I间实际上是?4KB为单位,所以要指定甌的虚拟空间的首地址的话Q参?应该?4KB的整数倍,甌的长度也应该?4KB的整数倍,即你不需要那么大?nbsp; <br>2、VirtualCopy的主要作用是映射物理地址I间Q如果参?为物理地址Q那么最后一个参数要dPAGE_PHYSICALQ参?必须?56的整数倍。如果参?拟地址Q?x80000000以上Q,那么最后一个参数就不要dPAGE_PHYSICALQW(xu)INCE内核?x)根据这个虚拟地址扑ֈ对应的物理地址?nbsp; <br>  <br><strong> 驱动E序和应用程序之间传递数据时何时调用MapPtrToProcessQ?nbsp; <br></strong>因ؓ(f)讑֤理器负责加载驱动程序DLLQ这意味着当应用程序调用驱动程序接口函数的时候,W(xu)INCE内核?x)将调用驱动E序接口函数的线E{Ud讑֤理器的q程I间然后执行具体的驱动程序代码,应用E序和设备管理器处于两个q程I间Q这造成讑֤理器无法访问应用程序传递的指针Q虚拟地址Q,所以当我们在应用程序中传递指针给驱动程序接口函数时QW(xu)INCE内核从中作了(jin)一个地址映射Q例如ReadFile、WriteFile、DeviceIoControl函数的参数凡是指针都l过?jin)映才传递给驱动E序Q所以很多驱动程序开发者ƈ不了(jin)解其中的奥秘可以编E了(jin)。但是如果参数是一个指向一个结构体的指针,而结构体里包括一个或多个指针Q那么WINCE内核q不负责映射Q所以就需要开发者在驱动E序接口函数中调用API函数MapPtrToProcess来映地址。例如:(x)pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());   <br>  <br> <strong>如何判断可插拔的讑֤是否存在Q?/strong>  <br>1、通过查找注册表的倹{凡是由API ActivateDeviceEx加蝲的驱动程序都在[HKEY_LOCAL_MACHINE\Drivers\Active]键下有注册键Q通过查找“name”或者其它键值就能够扑ֈ。设备管理器p用这个API。如果是PCI讑֤Q在注册表[HLM\Drivers\BuiltIn\PCI\Instance]下查扑օ键字Q例如[HLM\Drivers\BuiltIn\PCI\Instance\WaveDev1]Q说明音频驱动已l加载?nbsp; <br>2、调用驱动程序接口函敎ͼҎ(gu)q回值或者执行结果来判断?nbsp; <br>  <br> <strong>如何做到通过串口q来的一个信号启动自己开发的应用E序Q?nbsp; <br></strong>创徏一个线E负责等待串口过来的信号Q调用API SetCommMask讄要等待的信号U类Q具体可以等待的信号U类参见参数2的说明。然后再调用API WaitCommEvent函数{待q个信号Q接收之后再调用API CreateProcess启动应用E序?nbsp; <br>  <br><strong> 在WINCE中如何只能启动应用程序的一个实例?</strong>  <br>常用的两U办法:(x)  <br>1、如果应用程序实例创Z(jin)H口Q可通过API FindWindow函数通过H口cd和窗口标题名U来查找Q前提是pȝ内不?x)出现窗口名U重复的情况?nbsp; <br>2、应用程序初始化的时候创Z个事件或互斥{内核对象,因ؓ(f)内核对象是由内核创徏Q名U在pȝ内唯一?nbsp; <br>  <br><strong> 能不能自q辑一个数字签名文件导入到手机上,q样可以用q个{֐{自qE序?jin)?/strong>  <br>WINCE的内核签名机制的用途是限制非法的可执行模块EXE、DLL{在讑֤上运行。要求内核的加蝲模块用公钥验证请求加载的EXE、DLL的签名是否合法,而这个公钥是在定制内核的时候加q去的,所以除内核的定制者以外的人无法修改这个验证机制?nbsp; <br>  <br> 我按照版ȝ文章《加密WINCEpȝ》里操作Q提C错误如下:(x)  <br>Error 80090016 during CryptSignHash 1!  <br>Error signing hash  <br>q是因ؓ(f)传递了(jin)无效的钥容器名称QCryptoAPI调用p|。应该在使用signfile工具之前创徏一个钥容器Q在桌面Windows中调用API CryptAcquireContext创徏一个指定名U的钥容器,接着再创Z个签名密钥对Q这时再使用signfile工具可以了(jin)。我在文章里写成-kfulinlin是因为我创徏钥容器的时候没有指定名Uͼpȝ采用当前登录的用户名ؓ(f)容器名?nbsp; <br>  <br> <strong>~译错误QCVTRES : fatal error CVT1102: out of memory; 42 bytes required Q?/strong>  <br>多数情况下出现这U错误是因EVC的bug而vQ应该在安装EVC之后qd装EVC的SP补丁。另外ؓ(f)?jin)避开BUGQ用EVC~程应该L一些习(fn)惯,比如定期备䆾工程所有文Ӟ每次~译旉用Clean + Rebuild AllQ正调试时不要关闭模拟器{等?nbsp; <br>  <br><strong> 在WINCE下是否能够得到某一q程使用的物理内存总量Q?/strong>  <br>目前没发现有q样一个API能够得到指定q程使用的物理内存总量。只有GlobalMemoryStatus能够得到整个pȝ使用的物理内存总量?nbsp; <br>  <br><strong> 应用E序如何控制lcd的亮度?如何获得甉|的电(sh)量?</strong>  <br>从常见的q_如Geode、三星ARMpd来看Q的在驱动斚w没有l一的控制LCD或者其它种cdq亮度的接口函数Q所以只能根据具体^台提供的接口来做。从帮助文档来看微Y的带有DirectDraw功能的显C驱动程序的有标准的增加亮度的接口函数Q关于背景光参见标题?sh)?#8220;Enabling a Backlight”的帮助文档?nbsp; <br>获得甉|?sh)量有标准的接口函数GetSystemPowerStatusExQ前提是驱动E序和硬仉要支持?nbsp; <br>  <br> <strong>WINCE的socket函数好像不支持发?接收时Q?/strong>  <br>是的Q最早版本的WINCE支持选项SO_RCVTIMEO、SO_SNDTIMEOQ后来却不支持了(jin)?nbsp; <br>  <br> <strong>WINCE下如何设|窗口最大化和最化Q?/strong>  <br>WINCE的帮助文档在介绍API ShowWindow函数的参数时指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支持,但实际上q不完全是这P具体来说Q?nbsp; <br>SW_MAXIMIZE            比原来窗口大Q但不是最大化  <br>SW_MINIMIZE             ~译成功Q但是不起作?nbsp; <br>SW_SHOWMAXIMIZED     最大化  <br>SW_SHOWMINIMIZED      ~译出错  <br>SW_RESTORE              能恢?nbsp; <br>SW_SHOWDEFAULT        ~译出错  <br>SW_SHOWMINNOACTIVE   ~译出错  <br>SW_HIDE                  能够隐藏  <br>  <br><strong> 如何用程序调用控刉板的触摸屏校对程序?</strong>   <br>两种办法Q?nbsp; <br>1、调用API TouchCalibrate函数  <br>2、调用CreateProcessQ参?为L"\\windows\\ctlpnl.exe"Q参?为L"cplmain.cpl,9"?nbsp; <br>  <br> <strong>如何获得U盘或者其它类型的存储器d量和剩余可用定wQ?/strong>  <br>调用API GetStoreInfo得到扇区数、每扇区字节敎ͼ怹x(chng)d量。调用API GetDiskFreeSpaceEx得到剩余可用定w?nbsp; <br>  <br> <strong>三星2440头文件定?define IIC_BASE 0xB1400000 // 54000000Qdatasheet?4000000Q那么怎么转成0xB1400000Q?/strong>  <br>物理地址映射Ҏ(gu)分ؓ(f)两种Q一U静(rn)态映另一Uؓ(f)动态映。在OEMAddressTable中定义了(jin)物理地址与虚拟地址的映关pd于静(rn)态映,用VirtualCopy映射属于动态映,采用哪种办法都可以。问题(sh)提到的属于静(rn)态映,2440的BSP在map.a文g中定义了(jin)IIC控制寄存器的物理起始地址和对应的虚拟地址如下Q?nbsp; <br>DCD 0x91400000, 0x54000000, 1 ;  <br>在OEMAddressTable中定义的虚拟地址范围?x8000 0000?x9FFF FFFFQ这部分可缓存,适合内核E序和应用程序用,同时WINCE内核?xA000 0000?xBFFF FFFF中映了(jin)另一份,指向?jin)同L(fng)物理地址Q这部分不可~存Q适合驱动E序使用。三星ARM处理器带有L1U高速缓存,可缓存(sh)(x)提高执行效率。对于特D的讑֤寄存器适合映射C可缓存的虚拟地址?nbsp; <br>当驱动程序调用VirtualCopy?xB1400000地址dӞW(xu)INCE自动这个地址减去0x2000 0000Q也是0x91400000Q对应的物理地址是0x54000000Q也是IIC控制寄存器的物理起始地址?nbsp; <br>  <br> <strong>ZRAM的注册表如何保存数据Q?/strong>  <br>调用API RegCopyFile备䆾注册表。调用API RegRestoreFile恢复注册表,然后调用KernelIoControl热启动恢复生效?nbsp; <br>  <br> <strong>如何隐藏和显CwinCE下标准外壳的d栏?</strong>  <br> HANDLE  hTaskBar = FindWindow(L"HHTaskBar", NULL);   <br> ShowWindow(hTaskBar, SW_HIDE);   <br> ShowWindow(hTaskBar, SW_SHOWNORMAL);   <br>  <br> <strong>如果能让WINCE的IE览器播放flash动画Q?/strong>  <br>播放flash需要Macromedia Flash Player SDKQ参见http://www.adobe.com/products/flashplayer_sdk/。这和real player怼Q都需要WINCEq_的SDKQ都需要申诗?nbsp; <br>  <br> <strong>WINCE下内核模式和用户模式有什么区别?</strong>  <br>Z(jin)使读者能够详l了(jin)解WINCE的地址映射原理q有两种模式Q在q里我分几个部分说明Q?nbsp; <br>1、WINCE内核nk.exe的Q务是理操作pȝ核心(j)功能。按照OEMAddressTable的映要求,所有物理地址都映到0x80000000以上Q所以对于内核程序nk.exe和内核模式下的线E来_(d)只要讉K0x80000000以上的有效虚拟地址lMMUp够访问物理地址Q无需再映是内核模式的一个特炏V内核模式的W二个特Ҏ(gu)没有地址讉K限制Q内核模式线E可以访问Q何有效虚拟地址Q所谓有效虚拟地址是指有实际事物对应?nbsp; <br>2、用h式线E只能访?x80000000以下的虚拟地址I间QW(xu)INCE6.0之前版本的内ؓ(f)每个q程划分32MB的地址I间Q在不调用特D函数的情况下不能相互访问,q样的设计得WINCEpȝ更安全、更E_Q限制访问地址是用h式的W一个特炏V第二个特点是需要多一层映,如果U程要访问物理内存的话需要先映射?x80000000以上Q再lMMU讉K物理内存地址?nbsp; <br>WINCE的线E具有{UL(参考API GetCallerProcess的说明,有一个很好的例子Q,当应用程序的U程调用API或者调用驱动程序接口函数时Q该U程?x){Udgwes.exe、device.exe、filesys.exe{进E中执行Q{UL由WINCE内核操作的,它会(x)修改U程的上下文Q记录线E的当前q程、调用者进E、拥有者进E三个倹{?nbsp; <br>3、如果在定制内核的时候选择?#8220;Full Kernel Mode”Q那么在q个内核上运行的所有线E都处于内核模式Q即使调用SetKMode(FALSE)后线E仍然具有内核模式的特点Q能够访问Q何有效的虚拟地址。假讄有一?4MB RAM的WINCE产品QRAM映射?x80000000?x84000000Q如果线E处于内核模式,它就直接可以讉Kq个范围的虚拟地址Q?nbsp; <br>在OnButton1()中编?nbsp; <br>DWORD oldMode = SetKMode(FALSE);  <br>volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或?0x84000000-0x00019000)  <br>*piTemp = 12345;  <br>在OnButton2()中编?nbsp; <br>DWORD oldMode = SetKMode(FALSE);  <br>volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或?0x84000000-0x00019000)  <br>int iTemp = *piTemp;  <br>先只执行OnButton1()然后关闭E序Q再重启E序然后执行OnButton2()QiTemp仍然{于12345。结果说明了(jin)两点Q内核模式线E可以直接访?x80000000以上的有效虚拟地址Q我们写到RAM中的数据没有丢失Q说明虚拟地址有效?nbsp; <br>如果在定制内核的时候没有选择“Full Kernel Mode”Q那么在q个内核上运行的所有线E都处于用户模式。可以调用SetKMode(TRUE)使调用线E暂时处于内核模式,q是原来的假讄境,我再举个例子Q?nbsp; <br>在OnButton1()中编?nbsp; <br>DWORD oldMode = SetKMode(TRUE);  <br>volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或?0x84000000-0x00019000)  <br>*piTemp = 12345;  <br>在用h式下Q如果不调用SetKMode(TRUE)Q那么执?piTemp = 12345一定会(x)弹出对话框,提示地址讉K非法Q如果调用SetKMode(TRUE)׃?x)提C地址讉K非法Q而且在OnButton2()中仍然能得到12345q个倹{?nbsp; <br>通过q两个例子我怿读者能够完全了(jin)解两U模式的区别?jin)?nbsp; <br>4、WINCE提供?jin)两个函数SetKMode和SetProcPermissionsQ其中SetKMode能够把调用线E切换到内核模式Q还可以切换回用h式。SetProcPermissions + GetCurrentPermissionsd当前q程讉K权限l调用线E,SetProcPermissions (0xFFFFFFFF)能让调用U程讉K所有进E空_(d)但是调用U程仍然处于用户模式。SetKMode和SetProcPermissions函数使得用户模式的特点不那么明晰?nbsp; <br>如上所说一个应用程序的U程可能转移到其它两个进E地址I间中读写数据,而每一个线E在被创建的时候只有访问创建它的进E地址I间的权限,所以驱动程序开发者必d驱动E序d数据前调用SetKMode或者SetProcPermissions增加调用此函数的U程讉K其它q程I间的权限。如果一个应用程序的U程只{Ud一个进E地址I间Q一般ؓ(f)讑֤理器进Edevice.exeQ这U情况下不必增加U程讉K其它q程I间的权限,但如果驱动程序本w创Z(jin)一个线E,那还是要调用SetKMode或者SetProcPermissions增加新的U程讉K其它q程的权限的Q因为驱动程序创建线E时Q当前进Eؓ(f)讑֤理器,所以新U程只具有访问设备管理器q程I间的权限,而不具备讉K应用E序q程I间的权限?nbsp; <br>5、可能一个编写过单的驱动的初学者会(x)很疑惑,因ؓ(f)开发一个简单的驱动程序根本不需要调用这些函敎ͼ也没有调用过MapPtrToProcessQ那是因为如果标准流驱动接口函数的参Cؓ(f)指针QReadFile、WriteFile、DeviceIoControl参数都有指针Q,W(xu)INCE内核?x)自动映指针包含的地址Q但仅此而已Q其余Q何情况都要求开发者自行处理,比如接口函数的参数是一个指向结构体的指针PAQ而结构体中包括指针PBQPB指针必d接口函C映射Q映后才能讉KQ否则就?x)造成地址讉K非法。所以结构体中每个指针都要映?nbsp; <br>Z(jin)让读者能?jin)解其中的原因,我D个例子:(x)  <br>假设讑֤理器被加蝲到Slot4Q应用程序A被加载到Slot 8QA只有一个主U程TQT开始执行,按照WINCE的规定,正获得CPU的进E必L到Slot0Q那么在执行代码的时候A的所有虚拟地址都被减去一个偏Ud|也就?×0x02000000QA调用DeviceIoControlQ传递一个指向一个结构体的指针BQ而这个结构体中包含一个指针CQ指针C包含的地址假设?x00030000Q当执行DeviceIoControl时WINCE把设备管理器的进E地址I间映射到Slot0Q因为放在注册表[HKLM\Drivers\BuiltIn]下的驱动E序是由讑֤理器加载的Q自焉动程序的代码D被加蝲到设备管理器q程I间Q但是线E仍然是TQ此时T的当前所在进Eؓ(f)讑֤理器(CurrentProcessQ,A变成?jin)T的调用者进E(CallerProcessQ,T自动h?jin)访问调用者进E空间的权限。这时访问Slot0中的虚拟地址其实质就是访问设备管理器的进E地址I间Q要把地址加上一个偏Ud|也就?×0x02000000Q所以DeviceIoControl讉K指针C包含的地址时本应该加上8×0x02000000Q却加上4×0x02000000Q结果地址q不是设备管理器的合法区域,pȝ׃(x)提示地址讉K非法。而如果做?jin)一个映,指针C包含的地址׃(x)被加一个正的偏移|使地址处于A的地址I间Slot 8中,T此时h讉KAq程I间的权限,讉K到正的虚拟地址当然?x)得到正的数据了(jin)?nbsp; <br>  <br><strong> Z么WINCE目录下的例子用build+sysgen能够~译成EXE文gQ而我d的例子就不能~译呢?</strong>  <br>如果q个例子是一个应用程序,那么肯定包括代码文gQ?h .c .cppQ和资源文gQ?rc和其它资源文Ӟ(j)Qbuild工具Ҏ(gu)source文g内容把代码文件编译成lib文gQ资源文件编译成.res文gQsysgen工具Ҏ(gu)makefile文g内容source文g中列出的需要链接的各个库文件合q成一个EXE文g。所以说关键在于makefile文gQW(xu)INCE目录下凡是能够用build+sysgen~译的都在makefile中有如何链接的设|,而我们添加的例子当然没有在makefile中找到如何链接的讄Qnmake工具׃(x)提示不知道如何创建?nbsp; <br>  <br> <strong>pcienum.exeq什么用的?</strong>  <br>如果你要开发某一个PCI讑֤的驱动程序,首先要知道这个PCI讑֤的信息(如VendorID、DeviceID、BaseClass、SubClassQ和PCIȝ的信息。运行这个pcienum.exep得到相关信息。pcienum.exe提供?jin)源码,位置\Public\Common\Oak\Drivers\Ceddk\Test\Pcienum?nbsp; <br>  <br> <strong>wince下如何让操作pȝq入待机模式Q又如何把它Ȁz?</strong>  <br>通过注册表就可以讄Q前提是你的驱动和硬仉支持。注册表参见标题(sh)ؓ(f)“GWES Suspend Time-outs”的帮助文档?nbsp; <br>[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Power]  <br>    "BattPowerOff"=dword:300  <br>    "ExtPowerOff"=dword:0  <br>    "WakeupPowerOff"=dword:60  <br>    "ScreenPowerOff"=dword:0  <br>  <br> <strong>现有一个GPRS模块Q如何通过GPRSq接到InternetQ?/strong>  <br>1、先在内怸加入WAN下面的几个组Ӟ如RAS/PPP、TAPI。WINCE采用unimodem驱动Q所以不必担?j)没有Modem驱动的支持?nbsp; <br>2、WINCE启动后新Z个拨可接,比如名称?#8220;gprs1”Q输入用户名、密码、电(sh)话号码。电(sh)话号码不同,所采用的模式不一P例如“*99#”是GPRS模式Q?#8220;17201”是普通的数据模式Q速度差很多,价钱也差很多?nbsp; <br>3、开始连接,q接q程?x)在对话框中昄Q直到显C?#8220;q接成功”?nbsp; <br>4、打开览器或者自己开发的通讯软g试|络q接情况?nbsp; <br>5、关闭连接?nbsp; <br>6、保存[HKEY_CURRENT_USER\Comm\RasBook\gprs1]下的所有数据,d到project.reg中,重新~译后内怸有?jin)一个拨可?#8220;gprs1”?nbsp; <br>7、调用RAS函数可以修改拨号q接“gprs1”的参敎ͼ如用户名、密码、电(sh)话号码,但是不能修改g讄Q如波特率、串口、数据位、停止位{。RAS函数q能够拨受挂断。ؓ(f)?jin)修?gu)L特率可以多保存几个拨可接,也可以直接调用TAPI开发拨可YӞ另外WINCE自带的拨可接是有源码的Q位|在\PUBLIC\COMMON\OAK\DRIVERS\NETSAMP\CONNMC?nbsp; <br>  <br> <strong>采用ZHIVE的注册表如何删除用户保存在注册表中的数据Q恢复到出厂时的注册表?</strong>  <br>用户修改的数据保存在user.hv文g中,直接删除一定失败,所以不能通过删除文g实现恢复出厂讄。微软考虑C(jin)q个问题Q在WINCE启动q程中filesys.exe加蝲注册表时?x)调用OEMIoControl函数q传递一个IOCTLQ这个IOCTL在pkfuncs.h中定义如下:(x)  <br>#define  IOCTL_HAL_GET_HIVE_CLEAN_FLAG  CTL_CODE(FILE_DEVICE_HAL, 49, METHOD_BUFFERED, FILE_ANY_ACCESS)  <br>filesys.exe?x)分别传递参数HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERSQ如果返回gؓ(f)TRUE那么filesys.exe清除原来的注册表文gQ如果返回gؓ(f)FALSE那么filesys.exe保留原来的注册表文g。默认WINCEq没有实现这个IOCTLQ所以OEM要删除注册表文g必d~写q个IOCTL代码。代码的例子可参考标题(sh)ؓ(f)“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的帮助文档。另外必dioctl.h和ioctl.c两个文g中编写该代码。在ioctl.c文g中找到const OAL_IOCTL_HANDLER g_oalIoCtlTable[]Q添加I(yng)OCTL和对应的处理函数。要q一步了(jin)解这个全局数组Q参见标题(sh)ؓ(f)“IOCTL Library”的帮助文档?nbsp; <br>  <br> <strong>如何在不删除必要lg的前提下减小内核文g长度Q?/strong>  <br>要减内核文仉度首先要在用PB的定制内核向g选择自定义,也就是说对于每个lg都由自己来选择Q而不是选择PB的标准配|。但减小内核文g长度最有效最直接的办法是~小字体Q尤其对于东亚字体,采用字体压羃技术ƈ且选择合理的字库文件将明显~小文g长度?nbsp; <br>1、在定制内核旉择AGFA AC3 Font Compressionlg。SYSGEN变量为SYSGEN_AGFA_FONT?nbsp; <br>2、参考标题(sh)ؓ(f)“East Asian Font Versions”的帮助文档,从中选择你需要的字库文g加到内核中,从文档可以看出加AC3压羃比不加压~在文g长度斚w差距很大?nbsp; <br>  <br> <strong>如何得到WAV文g播放的L_(d)</strong>  <br>1、直接读取wav文g头信息,从文件v始地址偏移28个字节长度ؓ(f)4个字节保存的是每U钟播放的字节数Q从文g起始地址偏移40个字节长度ؓ(f)4个字节保存的是声x(chng)据的ȝ字节敎ͼ盔R是播放旉?nbsp; <br>2、调用IGraphBuilder::RenderFile打开一个wav文gQ然后通过IGraphBuilder得到IMediaSeeking指针Q再调用IMediaSeeking::GetDuration得到ȝ旉Q结果要除以10000000Q,IMediaSeeking::GetCurrentPosition得到当前播放旉?nbsp; <br>  <br> <strong>如何在Dialog-BasedE序中加入menubarQ?/strong>  <br>先调用CommandBar_Create再调用CommandBar_InsertMenubar?nbsp; <br>  <br> <strong>请问MultiByteToWideChar与_T、L、TEXT的区别?</strong>  <br>MultiByteToWideChar函数转换的对象可以是帔R也可以是变量。其它只能{换常量。_T和TEXT?x)根据当前系l是否定义_UNICODE宏来军_是否转换Q而L是转换成宽字符Q当然也包括其他cd帔R的{换?nbsp; <br>  <br> <strong>在用UBSU缆通过ActiveSync同步有效的情况下Q如何插上USBU缆后WINCE自动与PC同步Q?/strong>  <br>1、新Z个拨可接,假设名称?#8220;usb1”Q选择q接cd?#8220;直接q接”Qƈ在连接设备里选择通过USBU缆q接?nbsp; <br>2、将注册表[HKEY_CURRENT_USER\Comm\RasBook\usb1]下的数据d到project.reg或者platform.reg中?nbsp; <br>3、在[HKEY_CURRENT_USER\ControlPanel\Comm]下添加如下:(x)  <br>"AutoCnct"=dword:1  ///直接q接  <br>"Cnct"="usb1"       ///q接名称  <br>4、重新编译内核。ؓ(f)?jin)节省编译时间也可以在内核工E下搜烦(ch)*.reg文gQ将2?步骤中的注册表数据添加其中,然后直接make image?nbsp; <br>  <br> <strong>如何通过q程句柄来获得该q程的主H口句柄Q?/strong>  <br>好像没有API能够通过q程句柄直接获得ȝ口的句柄Q因为ƈ非每个应用程序都带UI。但是可以反q来Q先枚D当前pȝ所有主H口Q然后根据每个窗口的句柄调用GetWindowThreadProcessId函数得到q程的IDQ再调用OpenProcess得到q程句柄Q与现有的进E句柄比较?nbsp; <br>  <br> 我做的显C驱动DLL已经~译成功?jin),但是在加载显C驱动的q程中弹?gu)框,提示如下Q?nbsp; <br>unhandled exception  in  gwes.exe  (0xc0000005 access violation)  <br>提示的错误——地址讉K非法Q表明你的驱动程序代码ƈ没有在读写数据前dSetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函数让线E能够访问Q何进E的地址I间。你可以调用 IsBadReadPtr和IsBadWritePtr函数(g)地址是否能够合法讉K。编写和gwes有关的驱动程序应该首先调用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函数Q这是一个好?fn)惯?nbsp; <br>  <br><strong> 请问在嵌入式pȝ中如何设|GPRS拔号用的APNQ?/strong>  <br>对一个拨可接比?#8220;我的q接”单击鼠标右键Q在弹出的菜单中选择“属?#8221;Q然后单?#8220;配置”?#8220;拨号选项”Q在“附加讄”中添加AT命o(h)?#8220;+cgdcont=1,"ip","cmnet"”?#8220;cmnet”位置即ؓ(f)APN?nbsp; <br>  <br> <strong>WINCE的IP Phone功能如何Q?/strong>  <br>WINCE的voip需要c-s-cl构Q既需要服务器的中转,而skype采用W三代p2p技术就不需要中转,但是在gprs下也做不到语x(chng)畅。skype有pocket pc版本Q但是无U方面需要wlan或者cdma?nbsp; <br>  <br> <strong>三星ARMq_如何定义自己的中断IDQ?/strong>  <br>以S3C2410ZQ在oalintr.h文g中定义中断IDQ也USYSINTRQ例?nbsp;#define SYSINTR_MYINT  (SYSINTR_FIRMWARE+20)Q最大g能超qSYSINTR_FIRMWARE+23。然后在armint.c文g中找到OEMInterruptHandler函数Q用if (IntPendVal == INTSRC_XXX) 判断当前发生的中断源P然后q回SYSINTR_MYINT。内核分别调用OEMInterruptDisableQ禁止当前中断)(j)、OEMInterruptDoneQ中断处理结束)(j)、OEMInterruptEnableQ当前中断有效)(j)三个函数Q参数都Z断IDQ在q三个函C?nbsp;case SYSINTR_MYINT判断当前要处理的中断?nbsp; <br>  <br> <strong>如何开发Y件从PC端复制文件到ZWINCE的设备?</strong>  <br>调用RAPIQRemote Application Programming InterfaceQ函敎ͼ此函数集由桌面计机调用Q由ZWINCE的设备执行。一旦连接上可以在桌面计算机端调用RAPI。通过注册表还可以限制RAPI能够讉K目录的范围。具体参考RAPI和RDPQ远E桌面协议)(j)?nbsp; <br>  <br> <strong>请问如何对NandFlash分区、格式化Q?/strong>  <br>你看看WINCE420\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BOOTPART\bootpart.cppQ在Eboot中先要调用BP_LowLevelFormat(  <br>DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)再flash的一个区域徏立空的MBR,然后q箋(hu)两次调用BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)函数来徏立BINFS和FAT分区。徏好后Q将nk.bin烧入binfs分区中?nbsp; <br>  <br>  <strong>要做个弹出对话框h always on top 属性,如何实现Q?/strong>  <br>调用SetWindowPos(.. , HWND_TOPMOST, ...., SWP_NOACTIVATE)?nbsp; <br>  <br> <strong>s3c2410QWINCE下网lPING一?x)就断,如何解决Q?/strong>  <br>原因在于中断处理E序把已l生的中断标志清除掉了(jin)Q这样就丢失一ơ中断。因为原驱动里配|中断ؓ(f)上升沿触发,一ơ中断丢失就D不会(x)再生中断信可变,因ؓ(f)只有在中断服务中d?jin)cs8900?nbsp;Interrupt status queue寄存器后Q才?x)生下一ơ中断!解决办法Q?nbsp; <br>1、在cfw.c文g中全局定义BOOL Inited = FALSE  <br>2、修改OEMInterruptEnable()中case SYSINTR_ETHER: 下面的语句ؓ(f)Q?nbsp; <br>if(Inited == FALSE)   <br>{   <br>s2410IOP->rEINTPEND = 0x200;   <br>s2410INT->rSRCPND = BIT_EINT8_23;   <br>if (s2410INT->rINTPND & BIT_EINT8_23)   <br>s2410INT->rINTPND = BIT_EINT8_23;   <br>Inited = TRUE;   <br>}   <br>s2410IOP->rEINTMASK &= ~0x200;   <br>s2410INT->rINTMSK &= ~BIT_EINT8_23;   <br>breakQ?nbsp;  <br>注:(x)本解军_法{载于http://stoned.blogchina.com/stoned/3083045.htmlQ非我本人研I成果?nbsp; <br>  <br> <strong>已经搜烦(ch)到文Ӟ如何用CListBox以图标Ş式显C出来?</strong>  <br>CListCtrl        ListCtrl;  <br>CImageList      ImageList;  <br>ImageList.Create(IDB_BITMAP, 48, 2, RGB(0,0,0));  <br>ListCtrl.SetImageList(&ImageList, LVSIL_NORMAL);  <br>ListCtrl.InsertItem(iListIndex, strItem, 1);   <br>  <br> <strong>如何改变控制面板中电(sh)源属性对话框的尺?</strong>   <br>1、需要修改对话框的尺寸是因ؓ(f)对话框是以资源方式加载的Q不?x)根据当前系l显C分辨率而自我调节尺寸?nbsp; <br>2、安装WINCE后有一些组ӞfeatureQ的资源文g*.res已l有?jin),如果你不改变Q那么build内核的时候PB只是把这?res复制到工E目录下Q然后与*.obj合ƈ成EXE、DLL、CPL。所以修改了(jin).rc文g里面的对话框寸后要重新~译.rc文g?res文gQ然后再覆盖原来WINCE自带?res文g?nbsp; <br>3、改变对话框寸有两U办法:(x)一U方法是更改pȝ字体字号Q系l字体的字号变化?x)?jing)响对话框的尺寸,但是~点是所有系l字体有关的UI都会(x)改变。另一U是?rc文g中调整对话框寸Q然后编译成.res文gQ再?res复制到对应的语言目录里,比如目录名ؓ(f)0804Q中文)(j)Q再执行Rebuild命o(h)重新~译内核Q或者执行sysgenQbuild。在研究中我发现.res文g虽然能够直接用EVC打开、修攏V保存,但是和其它Obj链接成EXE、DLL、CPL后ƈ不能q行Q所以还是徏议读者用CE自带的rc工具~译最好。读者可在PB的命令行中键?#8220;rc /?”?jin)解rc.exe工具的用途和参数?nbsp; <br>  <br> <strong>使用EVC build之后q接模拟器的时候,提示download file{了(jin)一?x)又出现download failedQ?/strong>  <br>一般这L(fng)问题?sh)下面几个步骤解冻I(x)  <br>1、如果之前能启动模拟器而现在不能,那么先clean然后重启计算机再build?nbsp; <br>2、如果开发的L为WINXP+SP2Q可能存在与EVC模拟器不兼容的情况,(g)查C:\boot.iniQ将/noexecute=optin改ؓ(f)/execute=optin?nbsp; <br>3、检查你的模拟器是否能运行,假设你正用的SDK名称为MYSDKQ单击菜单tools—configure platform managerQ选择MYSDK—MYSDK emulatorQ再单击properties—testQ看看模拟器是否能够启动Q如果能启动那问题就不大?nbsp; <br>4、单击菜单build—update remote output filesQ看看模拟器是否能够启动?nbsp; <br>5、如果上q办法均不行Q关闭EVC然后重新建立一个新的工E,~译Q看看模拟器是否能够启动Q如果能启动说明原来工程Z(jin)问题Q最好恢复原工程的备份?nbsp; <br>  <br> <strong>如何讄能够自动拨号、禁止自动拨P</strong>  <br>在[HKEY_LOCAL_MACHINE\Comm\Autodial]下是自动拨号的注册表讄?nbsp; <br>Enabled=DWORD:1          ///是否能够自动拨号  <br>FailRetryWaitMS=DWORD    ///如果p|再次拨号的等待时?nbsp; <br>RasEntryName1= REG_SZ     ///自动拨号采用的拨可接名U?nbsp; <br>更多l节请参考标题(sh)ؓ(f)“Auto Dial Registry Settings”的帮助文档?nbsp; <img src ="http://www.shnenglu.com/kuronca/aggbug/49332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kuronca/" target="_blank">零宇</a> 2008-05-09 17:24 <a href="http://www.shnenglu.com/kuronca/archive/2008/05/09/49332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> (?成ؓ(f)嵌入式程序员应知道的10个基本问?http://www.shnenglu.com/kuronca/archive/2008/05/09/49330.html零宇零宇Fri, 09 May 2008 09:22:00 GMThttp://www.shnenglu.com/kuronca/archive/2008/05/09/49330.htmlhttp://www.shnenglu.com/kuronca/comments/49330.htmlhttp://www.shnenglu.com/kuronca/archive/2008/05/09/49330.html#Feedback0http://www.shnenglu.com/kuronca/comments/commentRss/49330.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/49330.html       从被面试者的角度来讲Q你能了(jin)解许多关于出题者或监考者的情况。这个测试只是出题者ؓ(f)昄其对ANSI标准l节的知识而不是技术技巧而设计吗Q这是个愚蠢的问题吗Q如要你{出某个字符的ASCII倹{这些问题着重考察你的pȝ调用和内存分配策略方面的能力吗?q标志着出题者也许花旉在微Z而不是在嵌入式系l上。如果上qCQ何问题的{案??的话Q那么我知道我得认真考虑我是否应该去做这份工作?br>       从面试者的角度来讲Q一个测试也许能从多斚w揭示应试者的素质Q最基本的,你能?jin)解应试者C语言的水q뀂不怎么P看一下这人如何回{他不会(x)的问题(sh)是满有趣。应试者是以好的直觉做出明智的选择Q还是只是瞎蒙呢Q当应试者在某个问题?sh)卡住时是找借口呢,q是表现出对问题的真正的好奇?j),把这看成学?fn)的机?x)呢Q我发现q些信息与他们的试成W一h用?br>       有了(jin)q些x(chng)Q我军_Z些真正针对嵌入式pȝ的考题Q希望这些o(h)人头痛的考题能给正在扑ַ作的Z点帮助。这些问题都是我q些q实际碰到的。其中有些题很难Q但它们应该都能l你一点启q?br>       q个试适于不同水^的应试者,大多数初U水q的应试者的成W?x)很差,l验丰富的程序员应该有很好的成W。ؓ(f)?jin)让你能自己军_某些问题的偏好,每个问题没有分配分数Q如果选择q些考题?sh)Z所用,误行按你的意思分配分数?br> 
 预处理器QPreprocessorQ?/strong>
 
 1 . 用预处理指o(h)#define 声明一个常敎ͼ用以表明1q中有多秒Q忽略闰q问题)(j)
          #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
 我在q想看到几g事情Q?br> 1) #define 语法的基本知识(例如Q不能以分号l束Q括L(fng)使用Q等{)(j)
 2)懂得预处理器ؓ(f)你计常数表辑ּ的|因此Q直接写Z是如何计一q中有多秒而不是计出实际的|是更清晰而没有代L(fng)?br> 3) 意识到这个表辑ּ一?6位机的整型数溢出-因此要用到长整型W号L,告诉~译器这个常数是的长整型数?br> 4) 如果你在你的表达式中用到ULQ表C无W号长整型)(j)Q那么你有了(jin)一个好的v炏V记住,W一印象很重要?br> 
 2 . 写一?标准"宏MIN Q这个宏输入两个参数q返回较?yu)的一个?br>         #define MIN(A,B) Q(AQ?<= (B) ? (A) : (B))
 q个试是ؓ(f)下面的目的而设的:(x)
 1) 标识#define在宏中应用的基本知识。这是很重要的。因为在  嵌入(inline)操作W?变(sh)ؓ(f)标准C的一部分之前Q宏是方便生嵌入代码的唯一Ҏ(gu)Q对于嵌入式pȝ来说Qؓ(f)?jin)能辑ֈ要求的性能Q嵌入代码经常是必须的方法?br> 2)三重条g操作W的知识。这个操作符存在C语言中的原因是它使得~译器能产生比if-then-else更优化的代码Q了(jin)解这个用法是很重要的?br> 3) 懂得在宏中小?j)地把参数用括号括v?br> 4) 我也用这个问题开始讨论宏的副作用Q例如:(x)当你写下面的代码时会(x)发生什么事Q?br>         least = MIN(*p++, b);
 
 3. 预处理器标识#error的目的是什么?
 如果你不知道{案Q请看参考文?。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会(x)读C语言课本的附录去扑և象这U问题的{案。当然如果你不是在找一个书呆子Q那么应试者最好希望自׃要知道答案?br> 
 
 d@环(Infinite loopsQ?/strong>
 
 4. 嵌入式系l中l常要用到无限@环,你怎么L(fng)C~写d@环呢Q?br> q个问题用几个解x(chng)案。我首选的Ҏ(gu)是:(x)
 
 while(1)
 {
 
 }
 
 一些程序员更喜Ƣ如下方案:(x)
 
 for(;;)
 {
 
 }
 
 q个实现方式让我为难Q因个语法没有确切表辑ֈ底怎么回事。如果一个应试者给?gu)个作为方案,我将用这个作Z个机?x)去探究他们q样做的基本原理。如果他们的基本{案是:(x)"我被教着q样做,但从没有惛_qؓ(f)什么?q会(x)l我留下一个坏印象?br> 
 W三个方案是?goto
 Loop:
 ...
 goto Loop;
 应试者如l出上面的方案,q说明或者他是一个汇~语aE序员(q也许是好事Q或者他是一个想q入新领域的BASIC/FORTRANE序员?br> 
 
 数据声明QData declarationsQ?/strong>
 
 5. 用变量al出下面的定?br> a) 一个整型数QAn integerQ?
 b)一个指向整型数的指针( A pointer to an integerQ?
 c)一个指向指针的的指针,它指向的指针是指向一个整型数Q?A pointer to a pointer to an integeQr
 d)一个有10个整型数的数l( An array of 10 integersQ?
 e) 一个有10个指针的数组Q该指针是指向一个整型数的。(An array of 10 pointers to integersQ?
 f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integersQ?
 g) 一个指向函数的指针Q该函数有一个整型参数ƈq回一个整型数QA pointer to a function that takes an integer as an argument and returns an integerQ?
 h) 一个有10个指针的数组Q该指针指向一个函敎ͼ该函数有一个整型参数ƈq回一个整型数Q?An array of ten pointers to functions that take an integer argument and return an integer Q?br> 
 {案是:(x)
 a) int a; // An integer
 b) int *a; // A pointer to an integer
 c) int **a; // A pointer to a pointer to an integer
 d) int a[10]; // An array of 10 integers
 e) int *a[10]; // An array of 10 pointers to integers
 f) int (*a)[10]; // A pointer to an array of 10 integers
 g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
 h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer 
 
    Zl常声称q里有几个问题是那种要翻一下书才能回答的问题,我同意这U说法。当我写q篇文章ӞZ(jin)定语法的正性,我的查?jin)一下书。但是当我被面试的时候,我期望被问到q个问题Q或者相q的问题Q。因为在被面试的q段旉里,我确定我知道q个问题的答案。应试者如果不知道所有的{案Q或臛_大部分答案)(j)Q那么也没有ؓ(f)q次面试做准备,如果该面试者没有ؓ(f)q次面试做准备,那么他又能ؓ(f)什么出准备呢?
 
 Static
 
 6. 关键字static的作用是什么?
 q个单的问题很少有h能回{完全。在C语言中,关键字static有三个明昄作用Q?br> 1)在函CQ一个被声明为静(rn)态的变量在这一函数被调用过E中l持其g变?br> 2) 在模块内Q但在函C外)(j)Q一个被声明为静(rn)态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量?br> 3) 在模块内Q一个被声明为静(rn)态的函数只可被这一模块内的其它函数调用。那是Q这个函数被限制在声明它的模块的本地范围内用?br> 
    大多数应试者能正确回答W一部分Q一部分能正回{第二部分,同是很少的h能懂得第三部分。这是一个应试者的严重的缺点,因ؓ(f)他显然不懂得本地化数据和代码范围的好处和重要性?br> 
 
 Const
 
 7Q关键字const有什么含意?
     我只要一听到被面试者说Q?const意味着常数"Q我q道我正在和一个业余者打交道。去qDan Saks已经在他的文章里完全概括?jin)const的所有用法,因此ESP(译者:(x)Embedded Systems Programming)的每一位读者应该非常熟(zhn)const能做什么和不能做什?如果你从没有d那篇文章Q只要能说出const意味着"只读"可以了(jin)。尽这个答案不是完全的{案Q但我接受它作ؓ(f)一个正的{案。(如果你想知道更详l的{案Q仔l读一下Saks的文章吧。)(j)
    如果应试者能正确回答q个问题Q我问他一个附加的问题Q?br>    下面的声明都是什么意思?
 
 const int a;
 int const a;
 const int *a;
 int * const a;
 int const * a const;
 
 /******/
    前两个的作用是一Pa是一个常整型数。第三个意味着a是一个指向常整型数的指针Q也是Q整型数是不可修改的Q但指针可以Q。第四个意思a是一个指向整型数的常指针Q也是_(d)指针指向的整型数是可以修改的Q但指针是不可修改的Q。最后一个意味着a是一个指向常整型数的常指针(也就是说Q指针指向的整型数是不可修改的,同时指针也是不可修改的)(j)。如果应试者能正确回答q些问题Q那么他q我留下了(jin)一个好印象。顺带提一句,也许你可能会(x)问,即不用关键?constQ也q是能很Ҏ(gu)写出功能正确的程序,那么我ؓ(f)什么还要如此看重关键字const呢?我也如下的几下理由:(x)
 1) 关键字const的作用是为给M代码的h传达非常有用的信息,实际上,声明一个参Cؓ(f)帔R是ؓ(f)?jin)告诉?jin)用户q个参数的应用目的。如果你曾花很多旉清理其它人留下的垃圾Q你׃(x)很快学会(x)感谢q点多余的信息。(当然Q懂得用const的程序员很少?x)留下的垃圾让别人来清理的。)(j)
 2) 通过l优化器一些附加的信息Q用关键字const也许能生更紧凑的代码?br> 3) 合理C用关键字const可以使编译器很自然地保护那些不希望被改变的参敎ͼ防止其被无意的代码修攏V简而言之,q样可以减少bug的出现?br> 
 
 Volatile
 
 8. 关键字volatile有什么含?q给Z个不同的例子?br>    一个定义ؓ(f)volatile的变量是说这变量可能?x)被意想不到地改变,q样Q编译器׃?x)去假设q个变量的g(jin)。精地说就是,优化器在用到q个变量时必Lơ都心(j)地重新读取这个变量的|而不是用保存在寄存器里的备份。下面是volatile变量的几个例子:(x)
 1) q行讑֤的硬件寄存器Q如Q状态寄存器Q?br> 2) 一个中断服务子E序中会(x)讉K到的非自动变?Non-automatic variables)
 3) 多线E应用中被几个Q务共享的变量
 
    回答不出q个问题的h是不?x)被雇䄦的。我认ؓ(f)q是区分CE序员和嵌入式系l程序员的最基本的问题。搞嵌入式的家伙们经常同g、中断、RTOS{等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将?x)带来灾难?br>    假设被面试者正地回答?jin)这是问题(嗯,怀疑是否会(x)是这P(j)Q我稍微深I一下,看一下这家伙是不是直正懂得volatile完全的重要性?br> 1)一个参数既可以是constq可以是volatile吗?解释Z么?br> 2); 一个指针可以是volatile 吗?解释Z么?br> 3); 下面的函数有什么错误:(x)
 
 int square(volatile int *ptr)
 {
         return *ptr * *ptr;
 }
 
 下面是答案:(x)
 1)是的。一个例子是只读的状态寄存器。它是volatile因ؓ(f)它可能被意想不到地改变。它是const因ؓ(f)E序不应该试囑֎修改它?br> 2); 是的。尽这q不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时?br> 3) q段代码有点变态。这D代码的目的是用来返指针*ptr指向值的qx(chng)Q但是,׃*ptr指向一个volatile型参敎ͼ~译器将产生cM下面的代码:(x)
 
 int square(volatile int *ptr)
 {
     int a,b;
     a = *ptr;
     b = *ptr;
     return a * b;
 }
 
    ׃*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,q段代码可能q不是你所期望的^方|正确的代码如下:(x)
 
 long square(volatile int *ptr)
 {
     int a;
     a = *ptr;
     return a * a;
 }
 
 位操作(Bit manipulationQ?/strong>
 
 9. 嵌入式系lL要用户对变量或寄存器q行位操作。给定一个整型变量aQ写两段代码Q第一个设|a(chn)的bit 3Q第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变?br>    对这个问题有三种基本的反?br> 1)不知道如何下手。该被面者从没做qQ何嵌入式pȝ的工作?br> 2) 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同~译器之间是不可UL的,同时也保证了(jin)的你的代码是不可重用的。我最q不q看?Infineon为其较复杂的通信芯片写的驱动E序Q它用到?jin)bit fields因此完全Ҏ(gu)无用Q因为我的编译器用其它的方式来实现bit fields的。从道dԌ(x)永远不要让一个非嵌入式的家伙_实际硬件的辏V?br> 3) ?#defines ?bit masks 操作。这是一个有极高可移植性的Ҏ(gu)Q是应该被用到的Ҏ(gu)。最佳的解决Ҏ(gu)如下Q?br> 
 #define BIT3 (0x1 << 3)
 static int a;
 
 void set_bit3(void)
 {
     a |= BIT3;
 }
 void clear_bit3(void)
 {
     a &= ~BIT3;
 }
 
    一些h喜欢|和清除D定义一个掩码同时定义一些说明常敎ͼq也是可以接受的。我希望看到几个要点Q说明常数、|=?amp;=~操作?br> 
 
 讉K固定的内存(sh)|(Accessing fixed memory ***sQ?/strong>
 
 10. 嵌入式系l经常具有要求程序员去访问某特定的内存(sh)|的特点。在某工E中Q要求设|一l对地址?x67a9的整型变量的gؓ(f)0xaa66。编译器是一个纯_的ANSI~译器。写代码d成这一d?br>    q一问题?gu)试你是否知道?f)?jin)访问一l对地址把一个整型数强制转换QtypecastQؓ(f)一指针是合法的。这一问题的实现方式随着个h风格不同而不同。典型的cM代码如下Q?br>     int *ptr;
     ptr = (int *)0x67a9;
     *ptr = 0xaa55;
 
  A more obscure approach is:
 一个较晦ӆ的方法是Q?br> 
     *(int * const)(0x67a9) = 0xaa55;
 
 即你的品味更接q第二种Ҏ(gu)Q但我徏议你在面试时使用W一U方案?br> 
 中断QInterruptsQ?/strong>
 
 11. 中断是嵌入式pȝ中重要的l成部分Q这D?jin)很多编译开发商提供一U扩展—让标准C支持中断。具代表事实是,产生?jin)一个新的关键字 __interrupt。下面的代码׃用了(jin)__interrupt关键字去定义?jin)一个中断服务子E序(ISR)Q请评论一下这D代码的?br> 
 __interrupt double compute_area (double radius)
 {
     double area = PI * radius * radius;
     printf("\nArea = %f", area);
     return area;
 }
 
 q个函数有太多的错误?jin),以至让h不知从何说v?jin)?x)
 1)ISR 不能q回一个倹{如果你不懂q个Q那么你不会(x)被雇用的?br> 2) ISR 不能传递参数。如果你没有看到q一点,你被雇用的机?x)等同第一V?br> 3) 在许多的处理?~译器中QQ点一般都是不可重入的。有些处理器/~译器需要让额处的寄存器入栈Q有些处理器/~译器就是不允许在ISR中做点q算。此外,ISR应该是短而有效率的,在ISR中做点q算是不明智的?br> 4) 与第三点一脉相承,printf()l常有重入和性能上的问题。如果你丢掉?jin)第三和W四点,我不?x)太为难你的。不用说Q如果你能得到后两点Q那么你的被雇用前景来光明了(jin)?br> 
 
 代码例子QCode examplesQ?/strong>
 
 12 . 下面的代码输出是什么,Z么?
 
 void foo(void)
 {
     unsigned int a = 6;
     int b = -20;
     (a+b > 6) ? puts("> 6") : puts("<= 6");
 }
    q个问题?gu)试你是否懂得C语言中的整数自动转换原则Q我发现有些开发者懂得极这些东ѝ不如何,q无W号整型问题的答案是输出?">6"。原因是当表辑ּ中存在有W号cd和无W号cd时所有的操作数都自动转换为无W号cd。因?20变成?jin)一个非常大的正整数Q所以该表达式计出的结果大?。这一点对于应当频J用到无W号数据cd的嵌入式pȝ来说是丰帔R要的。如果你{错?jin)这个问题,你也到了(jin)得不到q䆾工作的边~?br> 
 13. 评h(hun)下面的代码片断:(x)
 
 unsigned int zero = 0;
 unsigned int compzero = 0xFFFF;
 /*1's complement of zero */
 
 对于一个int型不?6位的处理器ؓ(f)_(d)上面的代码是不正的。应~写如下Q?br> 
 unsigned int compzero = ~0;
 
 q一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的l验里,好的嵌入式程序员非常准确地明白硬件的l节和它的局限,然而PC机程序往往把硬件作Z个无法避免的?ch)恼?br> C(jin)q个阶段Q应试者或者完全垂头气了(jin)或者信?j)满满志在必得。如果显然应试者不是很好,那么q个试在q里l束?jin)。但如果昄应试者做得不错,那么我就扔出下面的追加问题,q些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提?gu)些问题,我希望更多看到应试者应付问题的Ҏ(gu)Q而不是答案。不如何,你就当是q个׃?..
 
 
 动态内存分配(Dynamic memory al***Q?/strong>
 
 14. 管不像非嵌入式计算机那么常见,嵌入式系l还是有从堆QheapQ中动态分配内存的q程的。那么嵌入式pȝ中,动态分配内存可能发生的问题是什么?
    q里Q我期望应试者能提到内存片Q碎片收集的问题Q变量的持行旉{等。这个主题已l在ESP杂志中被q泛地讨?jin)(主要?P.J. Plauger, 他的解释q远过我这里能提到的Q何解释)(j)Q所有回q头看一下这些杂志吧Q让应试者进入一U虚假的安全感觉后,我拿?gu)么一个小节目Q?br>    下面的代码片D늚输出是什么,Z么?
 
 char *ptr;
 if ((ptr = (char *)malloc(0)) == NULL)
     puts("Got a null pointer");
 else
     puts("Got a valid pointer");
 
    q是一个有的问题。最q在我的一个同事不l意?gl了(jin)函数mallocQ得C(jin)一个合法的指针之后Q我才想到这个问题。这是上面的代码,该代码的输出?Got a valid pointer"。我用这个来开始讨L(fng)一问题Q看看被面试者是否想到库例程q样做是正确。得到正的{案固然重要Q但解决问题的方法和你做军_的基本原理更重要些?br> 
 Typedef
 
 15 Typedef 在C语言中频J用以声明一个已l存在的数据cd的同义字。也可以用预处理器做cM的事。例如,思考一下下面的例子Q?br> 
 #define dPS struct s *
 typedef struct s * tPS;
 
    以上两种情况的意N是要定义dPS ?tPS 作ؓ(f)一个指向结构s指针。哪U方法更好呢Q(如果有的话)(j)Z么?
    q是一个非常微妙的问题QQ何h{对q个问题Q正当的原因Q是应当被恭喜的。答案是Qtypedef更好。思考下面的例子Q?br> 
 dPS p1,p2;
 tPS p3,p4;
 
 W一个扩展ؓ(f)
 
 struct s * p1, p2;
 .
    上面的代码定义p1Z个指向结构的指,p2Z个实际的l构Q这也许不是你想要的。第二个例子正确地定义了(jin)p3 和p4 两个指针?br> 
 
 
 晦ӆ的语?/strong>
 
 16 . C语言同意一些o(h)人震惊的l构,下面的结构是合法的吗Q如果是它做些什么?
 
 int a = 5, b = 7, c;
 c = a+++b;
 
    q个问题做个测验的一个愉快的l尾。不你怸怿Q上面的例子是完全合乎语法的。问题是~译器如何处理它Q水q不高的~译作者实际上?x)争个问题,?gu)最处理原则Q编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:(x)
 
 c = a++ + b;
 
    因此, q段代码持行后a = 6, b = 7, c = 12?br>    如果你知道答案,或猜出正答案,做得好。如果你不知道答案,我也不把q个当作问题。我发现q个问题的最大好处是q是一个关于代码编写风|代码的可L,代码的可修改性的好的话题?br> 
 
    好了(jin)Q伙计们Q你现在已经做完所有的试?jin)。这是我出的C语言试题,我怀着愉快的心(j)情写完它Q希望你以同L(fng)?j)情d它。如果是认ؓ(f)q是一个好的测试,那么量都用C的找工作的过E中d。天知道也许q个一两年Q我׃做现在的工作Q也需要找一个?br>

零宇 2008-05-09 17:22 发表评论
]]>
水煮TCPMP (?http://www.shnenglu.com/kuronca/archive/2007/11/23/37188.html零宇零宇Fri, 23 Nov 2007 02:28:00 GMThttp://www.shnenglu.com/kuronca/archive/2007/11/23/37188.htmlhttp://www.shnenglu.com/kuronca/comments/37188.htmlhttp://www.shnenglu.com/kuronca/archive/2007/11/23/37188.html#Feedback0http://www.shnenglu.com/kuronca/comments/commentRss/37188.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/37188.htmldq底帮别人做一个项目,?jin)解了(jin)一下TCPMPQ觉得这个Y件的l构写得很好做?jin)些记录Q今天偶然翻出来看看觉得可能Ҏ(gu)在研I这个Y件的人有点帮助就贴出来。如果{载请注明出处Q谢谢?/p>

TCPMP是一个功能强大开攑ּ的开源多媒体播放器,
播放器主要由核心(j)框架模块Qcommon工程Q和解码器分d插gl成?br>TCPMP的插仉常多Q、libmad我们联合几个最常用的插Ӟffmpeg、splitterQ来说明Q其中interface插g实现TCPMP的界面,׃他和媒体播放没有什么关p,q部分可以完全被替换掉,替换成自q界面?br>ffmpeg工程是系l主要的韌频解码模块,ffmpeg是一个集录制、{换、音/视频~码解码功能Z体的完整的开源解x(chng)案。FFmpeg的开发是ZLinux操作pȝQ但是可以在大多数操作系l中~译和用。ffmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV{?0多种~码QAVI、MPEG、OGG、Matroska、ASF{?0多种解码。很多开源播攑֙都用C(jin)ffmpeg。但是ffmpegE序解码效率不是很高Q系l仅仅用了(jin)FFmpeg的部分解码功能?br>ffmpegȝ录下主要有libavcodec、libavformat和libavutil{子目录。其中libavcodec用于存放各个encode/decode模块Qlibavformat用于存放muxer/demuxer模块Qlibavutil用于存放内存操作{常用模块。本pȝ的媒体文件分d有单独的splitter模块完成所以不需要libavformat子目录。ffmpeg目录下libavcodec、libavutil保留子目录?/p>

libmad工程用于MP3文g解码Q该工程包含两个功能模块Q一个负责解析MP3文g格式Q包括MPEG1音频文g (MP1,MP2,MP3,MPA)Q读取每一帧音频数据;另一个负责解码MPEG1音频数据Q解码代码在libmad子目录中?br>libmad是一个开源的高精?MPEG1音频解码库,支持 MPEG-1QLayer I, Layer II ?LayerIIIQ也是 MP3Q。libmad提供 24-bit ?PCM 输出Q完全是定点计算Q非帔R合没有点支持的^C使用。?libmad 提供的一pd APIQ就可以非常单地实现 MP3 数据解码工作。在 libmad 的源代码文g目录下的 mad.h 文g中,可以看到l大部分该库的数据结构和 API {。libmad是用的fixed-integerQ通过整数模拟数计算的,_ֺ只能保证到小数点后第9位(大于0的最?0.00000000372529Q,虽然解码_ֺ?x)有损失Q但是极大提高(sh)(jin)解码效率Q特别是在嵌入式讑֤上也可以实现高码率MP3文g的解码?/p>

splitter工程用于解析多种韌频文件格式。可以解析的文g格式包括QASF媒体文gQ视频文?(AVI,DIVX)QW(xu)indows波Ş文g (WAV,RMP)QMPEG?sh)?jing)文g (MPEG,MPG,MPV)QMPEG4文g (MP4,3GP,M4A,M4B,K3G)。以上格式可以被解析但是数据~码不一定能正确解码Q需要依赖系l的解码器?/p>

common工程是核?j)模块,是一个开攄集数据输入、{换、音/视频解码、信可出等功能Z体的完整的多媒体播放框架。这个框架自w不包含M的Decode和Split功能Q这些功能由插g实现Q核?j)模块以一个树(wi)状结构管理所有的功能模块和插件模块,实现数据Render功能Q对输入、{换、输出流E的控制Q接受播放过E中的操作和对事件进行处理,同时也实现系l运行中l常使用的一些共用函敎ͼ比如解码q程中经怋用的逆离散余弦变换,内存操作Q界面中需要用的多语a字符处理{。common工程的主目录下主要有Qblit、dyncode、overlay、pcm、softidct、win32、zlib{子目录。其中blit和overlay存放是视频信h染模块,pcm存放PCM音频信号转换模块Qsoftidct存放逆离散余弦变换函敎ͼwin32存放内存操作{常用模块,dyncodeq个目录的代码比较晦涩,存放的是E序q行是动态生成代码模块,针对不同的CPU指o(h)集,PCM数据数据声道和采L(fng)不同Q视频渲染数据格式和色深{不同情况动态生成不同的优化代码Q这D代码非常精彩,不能不让Z服TCPMP作者的高超水^Q。核?j)模块有一个上下文对象contextQ该对象在初始化函数bool_t Context_Init(……)中候创Z(jin)一个该对象实例。该对象实例记录理各个功能模块Q用L(fng)面可以通过该对象和核心(j)模块交互Q管理控制播放过E?br> Context对象说明Q?br>typedef struct context
{
 int Version; //版本信息
 uint32_t ProgramId;
 const tchar_t* ProgramName;  //应用E序名称
 const tchar_t* ProgramVersion; //E序版本P字符?br> const tchar_t* CmdLine;   //E序命o(h)行信?br> void* Wnd;   //视频渲染H口句柄
 void* NodeLock;  //功能模块讉K临界Z斥变?br> array Node;   //功能模块数据对象数组
 array NodeClass;  //功能模块定义对象数组Q按照系l逻辑关系l织
 array NodeClassPri; //功能模块定义对象数组Q按照系l逻辑关系和模块优先排列
 array NodeModule;  //外部插g模块数组
 int LoadModuleNo;  //当前正在装蝲的外部插件序?br> void* LoadModule;
 array StrTable[2];  //字符串资源数l,字符串分?br>      //l底层用的标准字符串资源和
      //l界面用的昄字符串资源,两种资源用两个数l表C?br> array StrBuffer;
 array StrModule;  //未?br> void* StrLock;  //字符串数l访问(f)界区互斥变量
 uint32_t Lang;   //当前使用语言标志
 int CodePage;   //当前使用代码|?br> struct pcm_soft* PCM; //PCM音频信号转换模块
 struct blitpack* Blit; //视频信号渲染模块
 struct node* Platform; //得到q_相关信息
 struct node* Advanced; //得到播放模块高信息
 struct node* Player;  //播放控制模块
 notify Error;   //信息错误回调函数
 //屏幕旋{信息Q在某些pȝ中屏q可以旋?0度或180?br> int (*HwOrientation)(void*);
 void *HwOrientationContext;
 bool_t TryDynamic;  //未?br> int SettingsPage;   //未?br> size_t StartUpMemory;  //可以使用的有效内存数
 bool_t InHibernate;   //是否q入休眠状?br> bool_t WaitDisable;   //未?br> int FtrId;     //未?br> bool_t LowMemory;  //可以使用的有效内存数是否于pȝ要求的最低要?br> //动态代码生成中间状态及(qing)数据
 bool_t CodeFailed;
 bool_t CodeMoveBack;
 bool_t CodeDelaySlot;
 void* CodeLock;
 void* CodeInstBegin;
 void* CodeInstEnd;
 int NextCond;
 bool_t NextSet;
 bool_t NextByte;
 bool_t NextHalf;
 bool_t NextSign;
 
 uint32_t* FlushCache;  //未?br> void* CharConvertUTF8; //未?br> void* CharConvertCustom; //未?br> int CustomCodePage;  //未?br> void* CharConvertAscii; //未?br> void* Application;
 void* Logger;    //未?br> bool_t KeepDisplay;  //是否保持背光长亮
 int DisableOutOfMemory; //未?/p>

} context;
核心(j)模块上下文指针可以通过全局函数获得context* Context();
初始化上下文对象的全局函数是bool_t Context_Init(const tchar_t* Name,const tchar_t* Version,int Id,const tchar_t* CmdLine,void* Application);其中Name参数为应用程序名UͼVersion为版本信息字W串?br>释放上下文对象的全局函数是void Context_Done();?br>void Context_Wnd(void*);函数视频播攄口句柄初始化l设备上下文?/p>

功能模块包含定义对象和数据对象,定义对象描述功能模块怺间的逻辑l构Q数据对象记录模块属性和Ҏ(gu)?br>所有的功能模块l构按一个树(wi)状结构来l织Q结构关pd下,NODE是整个结构的根结点,其下为子节点Q节Ҏ(gu)cd可分为实节点Q全局节点Q设|节点,抽象节点?br>#define CF_SIZE   0x00FFFFFF
#define CF_GLOBAL  0x01000000
#define CF_SETTINGS  0x02000000
#define CF_ABSTRACT  0x08000000
抽象节点没有对应的对象实例,cMC++的抽象基c,Z(jin)按照逻辑关系l织pȝl构而存在,例如NODE是抽象节点。全局节点全局只有一个对象的实例Q如播放控制模块PLAYER_ID。设|节点表C和pȝ播放讄相关Q比如声韛_衡器模块EQUALIZER_IDQ颜色控制模块COLOR_ID。实节点与抽象节点不同,指可以生成对象实例的节点Q实节点没有Ҏ(gu)标识Q一般以数据对象占用内存大小表示是否是一个实节点Q创Ҏ(gu)要根据该信息分配内存单元Q实节点也可以有子节点,例如QMMS_ID的父节点是HTTP_ID。全局节点Q设|节点和实节点可以相互组合,比如播放控制节点同时是全局节点Q设|节点和实节炏V节点名U后带_ID的就是实节点Q否则就是抽象节炏V?/p>

    NODE Q根节点Q?br>    ├─FLOW Q流控制模块Q?br>    ?nbsp; ├─CODEC Q解码模块)(j)
    ?nbsp; ?nbsp; ├─EQUALIZER_ID Q声韛_衡器模块Q?br>    ?nbsp; ?nbsp; ├─VBUFFER_ID Q视频缓冲模块)(j)
    ?nbsp; ?nbsp; ├─DMO QDirectX Media ObjectQ?br>    ?nbsp; ?nbsp; ?nbsp; ├─WMV_ID
    ?nbsp; ?nbsp; ?nbsp; ├─WMS_ID
    ?nbsp; ?nbsp; ?nbsp; ├─WMVA_ID
    ?nbsp; ?nbsp; ?nbsp; ├─WMA_ID
    ?nbsp; ?nbsp; ?nbsp; └─WMAV_ID
    ?nbsp; ?nbsp; ├─FFMPEG VIDEO QF(tun)FMpeg 解码模块Q?br>    ?nbsp; ?nbsp; └─LIBMAD_ID QLibmad Mp3解码模块Q?br>    ?nbsp; ├─OUT Q信h染模块)(j)
    ?nbsp; ?nbsp; ├─AOUT Q音频信h染)(j)
    ?nbsp; ?nbsp; ?nbsp; ├─NULLAUDIO_ID
    ?nbsp; ?nbsp; ?nbsp; └─WAVEOUT_ID
    ?nbsp; ?nbsp; └─VOUT Q视频信h染)(j)
    ?nbsp; ?nbsp;     ├─NULLVIDEO_ID
    ?nbsp; ?nbsp;     └─OVERLAY
    ?nbsp; ├─IDCT Q离散余弦解码模块)(j)
    ?nbsp; ?nbsp; └─SOFTIDCT_ID
    ?nbsp; └─CODECIDCTQ离散余弦解码模块,函数比IDCT要少Q?br>    ?nbsp;     └─MPEG1_ID
    ├─MEDIA Q媒体文件格式编码解析模块)(j)
    ?nbsp; ├─FORMAT Q格式解析模块)(j)
    ?nbsp; ?nbsp; └─FORMATBASE
    ?nbsp; ?nbsp;     ├─RAWAUDIO
    ?nbsp; ?nbsp;     ?nbsp; └─MP3_ID
    ?nbsp; ?nbsp;     ├─RAWIMAGE
    ?nbsp; ?nbsp;     ├─ASF_ID
    ?nbsp; ?nbsp;     ├─AVI_ID
    ?nbsp; ?nbsp;     ├─MP4_ID
    ?nbsp; ?nbsp;     ├─MPG_ID
    ?nbsp; ?nbsp;     ├─NSV_ID
    ?nbsp; ?nbsp;     └─WAV_ID
    ?nbsp; ├─PLAYLIST Q播攑ֈ表模块)(j)
    ?nbsp; ?nbsp; ├─ASX_ID
    ?nbsp; ?nbsp; ├─M3U_ID
    ?nbsp; ?nbsp; └─PLS_ID
    ?nbsp; └─STREAMPROCESS Q数据流处理模块Q?br>    ├─STREAM Q数据输入模块)(j)
    ?nbsp; ├─MEMSTREAM_ID Q内存数据流模块Q?br>    ?nbsp; ├─FILE_ID Q文件IO模块Q?br>    ?nbsp; └─HTTP_ID Q网l数据获取模块)(j)
    ├─TIMER Q定时器模块Q?br>    ?nbsp; └─SYSTIMER_ID
    ├─ASSOCIATION_ID Q文件扩展名自动兌模块Q?br>    ├─ADVANCED_ID Q高U设|模块)(j)
    ├─COLOR_ID Q颜色控制模块)(j)
    ├─PLATFORM_ID Q^C息模块)(j)
    ├─XSCALEDRIVER_ID QIntel XScale CPU 信息模块Q?br>    ├─PLAYER_ID Q播放控制模块)(j)
    └─PLAYER_BUFFER_ID Q播攄冲模块)(j)
   
    节点?wi)状l构pq个?rn)态定义对?nodedef)实例实现Q?br>        typedef struct nodedef
  {
   int    Flags;
   int    Class;
   int    ParentClass;
   int    Priority;
   nodecreate  Create;
   nodedelete  Delete;
  } nodedef;
 Flags表示当前节点的类型:(x)抽象、实节点、全局、设|?br> Class表示当前节点的标识,如MEDIA_CLASS或ASF_ID{等?br> ParentClass表示当前节点的父节点标识Q如SYSTIMER_ID对象的父节点是TIMER_CLASS?br> Priority表示当前节点优先U?br> Create和Delete是两个函数指针,表示该节点的创徏函数和销毁函数?br> 如播放控制模块的l构定义?br> static const nodedef Player =
 {
  sizeof(player_base)|CF_GLOBAL|CF_SETTINGS,
  PLAYER_ID,
  NODE_CLASS,
  PRI_MAXIMUM+600,
  (nodecreate)Create,
  (nodedelete)Delete,
 };
 
 l大多数节点都有一个对应的数据对象Q记录该节点的数据和Ҏ(gu)Q每一个子节点对象都是以父节点对象作ؓ(f)该节点一个元素,cMC++的封装承机制。如果子节点的父节点没有数据对象Q该节点可以从node节点直接l承。每一个节炚w可以看成Node节点的直接或间接子节点,所以所有节点头以一个相同的nodel构开_(d)子节点可能还有自q属性,在承父对象后就是子节点自己的元素?br>    typedef struct node
 {
  int   Class;
  nodeenum Enum;
  nodeget  Get;
  nodeset  Set;
 } node;
 Class表示该对象的标识Q如PLAYER_ID?br> Enum是一个函数指针,指向一个函数用于枚丑ֽ前节点的属性?br> Get是一个函数指针,得到当前节点某一属性倹{?br> Set是一个函数指针,讄当前节点的某一属性数倹{?br> 
 节点的属性值数据特性在一个static const datatable xxxParams[] = {……};的静(rn)态数l里定义?br> typedef struct datatable
 {
  int No;
  int Type;
  int Flags;
  int Format1;
  int Format2;
 } datatable;
 
 No表示属性的标识Q如播放控制模块?define PLAYER_PLAY 0x32 pC控制播攑֙播放或暂停?br> Type表示属性的数据cdQ可用值在node.h中定义?br> Flags是属性数据的标志Q表C数据是不是只L据,是否有最大最值等{,可用值在node.h中定义,如果该标志包含DF_SETUP同时不包含DF_NOSAVE和DF_RDONLY属性,该属性会(x)被记录在注册表中Q下ơ启动时用注册表的数据初始化该属性?br> Format1和Format2是可选标志与Flags配合使用Q比如如果Flags表示该属性存在最大最|Format1和Format2可以分别表示最和最大数倹{?br> 
 在在pȝ上下文对象中有两个元素记录节点信息array Node;和array NodeClass;Qarray是数l数据类型,Node是节Ҏ(gu)据对象的数组QNodeClass节点对象的数l,按照pȝ逻辑关系l织?br> 创徏节点时传入nodedef对象到节点创建函敎ͼ函数?x)根据nodedef信息生成对应nodeclass对象d到NodeClass数组Q同时根据nodedef信息分配数据对象的内存空间。在该节点的Create函数里面再初始化该节点的数据对象?/p>

在所有功能模块中和界面加交互的主要就是播放控制模块struct node* Player;使用Ҏ(gu)如下Q?br>context* p = Context();
player* myplayer = NULL;
if(p) myplayer = (player*)(p->Player);
控制播放参数使用Set(void* This,int No,const void* Data,int Size);函数Q第一个参数是播放模块指针Q第二个参数是控制代码,卌q行什么操作,W三个参数是需要赋值给控制代码的数|最后一个参数是所赋数值的占用内存的大?br>例如开始播攄代码是:(x)
myplayer->Set(myplayer,PLAYER_PLAY,1,sizeof(int));
PLAYER_PLAY为控制代码,表示当前控制的是播放暂停功能Q数gؓ(f)1表示播放?表示暂停?br>得到某一控制属性用Get(void* This,int No,void* Data,int Size);函数Q参数含义和Set函数相同?br>控制代码是一l宏Q定义在player.h文g中。比较重要的控制参数?br>// play or pause (bool_t)
#define PLAYER_PLAY   0x32
// position in fraction (fraction)
#define PLAYER_PERCENT  0x25
// position in time (tick_t)
#define PLAYER_POSITION  0x28
// current format (format*)
#define PLAYER_FORMAT  0x2B
// current file in playlist (int)
#define PLAYER_LIST_CURRENT 0x2F
// current file index (suffled) in playlist (int)
#define PLAYER_LIST_CURRIDX 0xA2
// fullscreen mode (bool_t)
#define PLAYER_FULLSCREEN 0x3E
// stop
#define PLAYER_STOP   0xB2
// skin viewport rectangle (rect)
#define PLAYER_SKIN_VIEWPORT 0x3C
播放控制模块所有可用参数见static const datatable PlayerParams[]l构?/p>

d一个媒体文件到播放模块使用int PlayerAdd(player* Player,int Index, const tchar_t* Path, const tchar_t* Title);
W一个参Cؓ(f)播放模块指针Q第二个参数是添加到播放模块文g队列的序P如果是文g成ؓ(f)W一个文件该参数设ؓ(f)0Q第三个参数是媒体文件的目录和名UͼW四个参Cؓ(f)媒体文g标题Q该参数可以忽略?/p>

核心(j)模块也管理多语言字符Ԍ使用函数const tchar_t* LangStr(int Class, int Id);和const tchar_t* LangStrDef(int Class, int Id)可以得到对应字符Ԍpȝ字符串资源有两种Q标准字W串和特D字W集字符丌Ӏ标准字W串资源文g是工E目录下的lang_std.txt文gQ该文g字符串ؓ(f)ASCII字符Q可与其他代码页字符兼容。该文g记录的是核心(j)模块q行旉要用的字符ԌDecode和Splite模块可以处理的编码格式和文g格式也在q个文g中记录,例如lang_std.txt文g中的
MP3_0001=audio/mpeg
MP3_0002=mp1:A;mp2:A;mp3:A;mpa:A
MP3_0200=acodec/0x0055
U录?jin)MP3文g分离器对应的文gcd、扩展名和文件特征码?br>要得到标准字W串使用函数LangStrDefQ第一个参数表C字W类别,W二个参数表C字WID。界面相关的是特D字W集的字W串Q用函数LangStrQ第一个参数表C字W类别,W二个参数表C字WID。关于字W串资源文gl构含义在以后的文档中说明?a >http://blog.csdn.net/navi_dx/archive/2007/11/14/1885780.aspx



零宇 2007-11-23 10:28 发表评论
]]>
代码书写l节http://www.shnenglu.com/kuronca/archive/2007/08/28/31048.html零宇零宇Tue, 28 Aug 2007 12:36:00 GMThttp://www.shnenglu.com/kuronca/archive/2007/08/28/31048.htmlhttp://www.shnenglu.com/kuronca/comments/31048.htmlhttp://www.shnenglu.com/kuronca/archive/2007/08/28/31048.html#Feedback0http://www.shnenglu.com/kuronca/comments/commentRss/31048.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/31048.html好久Q没来这里写些什么了(jin)。这两个月一直忙着工作Q今天忽焉下来Q想x(chng)q两个月到的一些细节问题(sh)大家׃n下。好Q老样子先看段代码:
在脓(chung)代码前,我先做个声明Q代码在windowsq_下运行。做UI的朋友经常用到DrawText()q个APIQ它里面有个参数是关于文字对齐方式的. 我们写控件输Z息时Q都考虑增加q么cd的变量来控制文字信息输出Q最典型的就是按钮。一般情况下Q我们无需(g)该变量Q直接引用就好。但有时候ؓ(f)?jin)让界面更h性化Q我们需要检该变量Qƈ做些调整。好Q现在看q段代码Q?br> 它根据对齐属性是否包?DT_LEFTQ而做一些工?br>void OnPaint()
{
      。。。。。。?br>      。。。。。。?br>
      if(  m_uAlign  &  DT_LEFT )                                                      //代码 D?1
            DoA();
      else
            DoB();

      if( m_uAlign  &  DT_LEFT  ==  DT_LEFT )                              //代码 D?nbsp;2
            DoA();
      else
            DoB();

      if( (m_uAlign  &  DT_LEFT ) ==  DT_LEFT )                            //代码 D?nbsp;3
            DoA();
      else
            DoB();

      。。。。。。?br>}

上面三个代码D늚执行q程为:(x)1Q永q执?DoB() 函数体;
  2Q如?m_uAlign 最末位是零 Q则执行 DoB()函数?   否则则执?DoA()函数体;

3Q只?m_uAlign 包含 标志?DT_LEFT Q则执行 DoA()函数?   其他则执?DoB()函数体;

 貌似Q?? 都不是我们想要的。只?是正的。造成q种现象的原因是什么?
1Q?nbsp; q个不容易查出来Q我们一贯的写法都这h么?x)不对呢Q?其实Q我们看看他的定义就知道?#define DT_LEFT  0x00000000 
        呵呵Q缘由出来了(jin)Q?br>2 Q有? Q? 更单了(jin)Q就是运符优先U的问题Q?br>3Q正;它演CZ(jin)良好的代码风|

ȝQ其实这不算大问题,都是l节上的问题。可是细节上的问题,往往是最不容易察觉的Q就你发现问题Q可是想对代码段的定位更是困难,他们是隐形的虫子。ؓ(f)此,我们有必要养成良好的代码书写?fn)惯和风根{对今天遇到的问题,我ȝ两条Q?br>a)  在进行位标志(g)时Q一定要检结果与原值比较;
b) 在你不确定运符的优先Ӟ请一定要用括hhQ?br>今天Q就写道q里。希望这两条对大家有帮助。以后碰到类似问题,能想到就好!

零宇 2007-08-28 20:36 发表评论
]]>
WTL ---Good Boy!http://www.shnenglu.com/kuronca/archive/2007/05/30/25132.html零宇零宇Wed, 30 May 2007 08:44:00 GMThttp://www.shnenglu.com/kuronca/archive/2007/05/30/25132.htmlhttp://www.shnenglu.com/kuronca/comments/25132.htmlhttp://www.shnenglu.com/kuronca/archive/2007/05/30/25132.html#Feedback0http://www.shnenglu.com/kuronca/comments/commentRss/25132.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/25132.html      唉,说来惭愧。记得在前面说过Q打在五一期间研究下PPC上怎么l程序换肤,l果计划不如变化Q拜见未来的岳父x(chng)׃(jin)3天,同学l婚׃(jin)一天。回来后Q也没啥?j)思搞?jin),不过大概q是知道些东ѝ要通过hook技术达到换肤的Ҏ(gu)Q还是比较困隑֜啊。好?jin),q去的不说了(jin)。不q,以后我有Z(x)q是?x)l搞搞(现阶D|的还是少啊)(j)?br> 
      现在切入正题QWTL 。什么是WTLQWTL 的全UCؓ(f) Windows Template LibraryQ?是微软ATL开发组成员Nenad Stefanovic先生?span style="COLOR: red">ATL Windowing机制上发展v来的一整套GUI框架。它q用模板QtemplateQ技?/span>l织和创建GUI对象Q构成了(jin)_ֈ的面向对象框Ӟ佉K向对象与模板达成?jin)精制的融合?br>
      上面是WTL的定义,准确地描qC(jin)什么是WTL。请注意我用U色标记的两个地方,那可以说是WTL的精髓。首先,W(xu)TL其实ZATL的,它是ATL面向GUI~程的扩展;其次QW(xu)TLq用模板技术,q样构徏的程序精致短?br>
       需要指出的是WTL目前不被微Y官方支持也没有开发文档,不过能够在其官方|站下到sdk。WTL貌似在民间非常受Ƣ迎Q用q的人都说好, 甚至有h说会(x)过MFC。现在最新版的WTL?.0 beta2版,07q??8日才发布的?br> 
      Ҏ(gu)WTL和MFCQ他们大部分是相通的。对于一个有qMFC~程l验的h来说Q熟(zhn)WTLq是比较Ҏ(gu)的。下面是他们的比?br>
MFC WTL
Stand-alone library Yes No (built on ATL)
Yes Yes
Yes No
Yes No (Supported by volunteers inside MS)
Yes No
Yes Yes
Yes No
Yes Yes
No Yes
No (MFC does provide dialog bars) Yes
Yes Yes
Yes Yes
Yes Yes
Yes Yes
Yes Yes
No Yes
Yes Yes
Yes No
Yes Yes
Yes Yes (not as extensive as MFC)
Yes Yes
Yes Yes
No Yes
Yes Yes
Yes Yes
Yes Yes
No No
Yes Yes
No Yes
228KB +
MSVCRT.DLL (288KB)
24k (with /OPT:NOWIN98)
(+ MSVCRT.DLL if you use CString)
24KB +
MFC42.DLL (972KB) +
MSVCRT.DLL (288KB)
N/A
CRT (+ MFC42.DLL, if dynamically linked) None (CRT if you use CString)

        听说从WTL7.5开始支持PPC上编E,q可让我大ؓ(f)开?j)。有Z(x)试试用WTL在PPC上写个程序?/p>

零宇 2007-05-30 16:44 发表评论
]]>
用户层下拦截pȝapi的原理与实现 (转蝲) http://www.shnenglu.com/kuronca/archive/2007/04/28/23126.html零宇零宇Sat, 28 Apr 2007 09:23:00 GMThttp://www.shnenglu.com/kuronca/archive/2007/04/28/23126.htmlhttp://www.shnenglu.com/kuronca/comments/23126.htmlhttp://www.shnenglu.com/kuronca/archive/2007/04/28/23126.html#Feedback0http://www.shnenglu.com/kuronca/comments/commentRss/23126.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/23126.html阅读全文

零宇 2007-04-28 17:23 发表评论
]]>
又是一q“五一黄金周?/title><link>http://www.shnenglu.com/kuronca/archive/2007/04/26/22868.html</link><dc:creator>零宇</dc:creator><author>零宇</author><pubDate>Thu, 26 Apr 2007 03:29:00 GMT</pubDate><guid>http://www.shnenglu.com/kuronca/archive/2007/04/26/22868.html</guid><wfw:comment>http://www.shnenglu.com/kuronca/comments/22868.html</wfw:comment><comments>http://www.shnenglu.com/kuronca/archive/2007/04/26/22868.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/kuronca/comments/commentRss/22868.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kuronca/services/trackbacks/22868.html</trackback:ping><description><![CDATA[          又是一q?#8220;五一黄金?#8221;Q?#8220;五一”一到感觉一q去?jin)一半,旉飞逝啊Q当初也不知道谁提出q么个概念,搞得全国上下、祖国各地、大江南北都人声鼎沸QR水马龙(不知道成语用的对不?<img src="http://www.shnenglu.com/CuteSoft_Client/CuteEditor/images/emembarrassed.gif" align=absMiddle border=0>Q好一z荣景象,q让我想起一个比喻:(x)p时候的马蜂H吧Q^时看不出来马蜂多Q可是经孩们一捣鼓那出来的可是黑压压的一片。把全国同胞(yu)比作马蜂是有点不合适啊Q是谁又把全国同?yu)给捣鼓的出安Q?br><br>           唉,不管那么多了(jin)。以前出ȝQ回来感觉就是花׃|受Q还要冒着被h骗的风险Q说风险有点q了(jin)<img src="http://www.shnenglu.com/CuteSoft_Client/CuteEditor/images/emwink.gif" align=absMiddle border=0>Q,所以今q不凑那份热闹,老实在家呆着?br><br>            计划都定下来Ql研I些专业斚w东东。前D|间研I过E序换皮肤,准备x(chng)到PPC上看看,让PPC界面更美观。看C的换皮肤大致原理是Q先N子钩住界面主U程Q然后在控g创徏的时候捕捉控Ӟ然后再子cd。这个在PC上没问题Q可是到PPC上碰到关键的一步不能实现。那是PPC上不支持钩子函数Q这成Z个大的障:(x)没法钩住ȝE,无法子cd。原本想q在App的PreTranslateMessage中过滤子控g的wm_create消息Q从而实现子cd可是p|?jin)。我觉得解决问题关键核心(j)是:(x)除了(jin)钩子外,q有什么方法能在程序收到消息前劫获消息。这是我在“五一黄金?#8221;主要研究的东东,不过不知道自p否成功?br><br>          如果换皮肤研I进行顺利的话,准备把前D|间写?nbsp;用oledb 讉Ksqlmobile数据的类完善下。现在这些类仅仅提供?jin)基本操作,打算丰富让这些类的操作。不q由于种U原因,我将不提供源码,到时候可能以 dll形式或者com形式发布?br><br>          最后说两句Q现阶段制定计划是这P到时候不知道?x)执行的怎样Q有太多不可预知因素Q反正尽力吧Q?br>           <img src ="http://www.shnenglu.com/kuronca/aggbug/22868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kuronca/" target="_blank">零宇</a> 2007-04-26 11:29 <a href="http://www.shnenglu.com/kuronca/archive/2007/04/26/22868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Do What You think !http://www.shnenglu.com/kuronca/archive/2007/04/02/21097.html零宇零宇Mon, 02 Apr 2007 08:23:00 GMThttp://www.shnenglu.com/kuronca/archive/2007/04/02/21097.htmlhttp://www.shnenglu.com/kuronca/comments/21097.htmlhttp://www.shnenglu.com/kuronca/archive/2007/04/02/21097.html#Feedback5http://www.shnenglu.com/kuronca/comments/commentRss/21097.htmlhttp://www.shnenglu.com/kuronca/services/trackbacks/21097.htmlQ还是毛d的哲学思想分析的透彻Q事物的内因d事物的发展方向! Q,一直导致想法始l没能走出我的脑瓜瓜Q!现在不同拉, 因ؓ(f)脑瓜瓜里面多拉一条新的想法:(x)Do What You think !Q?br>
       写第一文章,实在没想到好的文章标题!在眼球环转屏q时Q看到博客标题,whaQ?׃刚开博客太兴奋?Q这么好的一句话Q怎么没惌v来!Q朋友,Ƣ迎来到我的博客Q每ơ的到来让我们一?Do What You think !Q?br>
      其次Q很荣幸加入q个大家庭。唉Q自己文W实在不好,始终想不出来写些啥!记得以前高(sh)每次模拟考,语文我都q黑名单Q?50分卷子,70分都拿不刎ͼ(j)Q这D实在写不出来,p么凑或吧Q?br>
      最后,说说标题的意思,其实也没什么深ȝ含义。只是这句话Q觉着吧对我作用满大的。有x(chng)量dQ简单不? 标题意思也解释清楚?jin),我也该去L下!

         do
         {
               if(you.HaveThink())
               {
                     you. DoThink();
               }
         }while( you.StillCanThink());

零宇 2007-04-02 16:23 发表评论
]]>
XxŷʸƷþþþþ| þþɫۺϾɫ99| þ91ƷۺϹҳ| ɫþþþþþС˵| Ʒþþþû| ɫþAVۺ| þþƷ| þþþó˾ƷĻ| պþþþĻ| þѾƷƵ| ɫվþþþۺywww| ٸþĻ | Ʒþþþþ| 69Ʒþþþùۿ| ھƷþþþþþ| 99ƷþþƷ| þþƷaĻؿ þþƷa޹v岻 | þþƷaĻؿ| ˳ɵӰվþ| ˺ݺۺ88ۺϾþ| һaƬþëƬ| þóۺɫۺ| ޹Ʒþþò | þˬƬţţ| þþþþavѿƬ| þþþþۺһĻ| þøݾƷԴվ| ޾þþþþ| þԭƷ| þwwƷw˳| þѵľƷV | þþù| 99þóĻ| þAV| þþþ99ƷƬŷ| ƷVAþþþþþñ| 2021þùԲľƷ| þۺϾþۺϾþۺ| Ʒþþþþùţţapp| ƷžžþþƷŮͬŷպۺ| Ʒþþþþù91|