|
AND_CATCHAND_CATCH
AND_CATCH(exception_class,exception _object_point_name) 说明: 定义一个代码块,它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型,然后使用 AND_CATCH宏获得随后的异常处理代码可以访问异常对象(若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用 THROW_LAST宏以便把处理过程移到下个外部异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾。 注释: AND_CATCH块被定义成为一个C++作用域(由花括号来描述)。若用户在此作用域定义变量,那么记住他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量。 ASSERT ASSERT(booleanExpression) 说明: 计算变量的值。如果结构的值为0,那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0,那么什么也不做。 诊断消息的形式为: assertion failed in file in line 其中name是元文件名,num是源文件中运行失败的中断号。 在Release版中,ASSERT不计算表达式的值也就不中断程序。如果必须计算此表达式的值且不管环境如何那么用VERIFY代替ASSERT。 注释: ASSERT只能在Debug版中用 ASSERT_VAILD ASSERT_VAILD(pObject) 说明: 用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数(把它们作为自己的变量来传递)。在 Release版中ASSERT_VALID什么也不做。在DEBUG版中,他检查指针,以不同于NULL的方式进行检查,并调用对象自己的 AssertValid成员函数。如果这些检测中有任何一个失败的话,那么他会以与ASSERT相同的方法显示一个警告的消息。 注释: 此函数只在DEBUG版中有效。 BEGIN_MESSAGE_MAP BEGIN_MESSAGE_MAP(the class,baseclass) 说明: 使用BEGIN_MESSAGE_MAP开始用户消息映射的定义。在定义用户类函数的工具(.cpp)文件中,以BEGIN_MESSAGE_MAP宏开始消息映射,然后为每个消息处理函数增加宏项,接着以END_MESSAGE_MAP宏完成消息映射。 CATCH CATCH(exception_class,exception_object_pointer_name) 说明: 使用此用定义一个代码块,此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对象,如何合适的话,就会得到关于异常的特殊原因的更多消息。调用THROW_LAST宏以把处理过程一下一个外部异常框架,如果exception-class是类CExceptioon,那么会获取所有异常类型。用户可以使用CObject::IsKindOf成员函数以确定那个特别异常被排除。一种获取异常的最好方式是使用顺序的 AND_CATCH语句,每个带一个不同的异常类型。此异常类型的指针由宏定义,用户不必定义。 注释: 此CATCH块被定义作一个C++范围(由花括号描述)。如用户在此范围定义变量,那么它们只在吃范围内可以访问。他还可以用于异常对象的指针名。 DEBUG_NEW #define new DEBUG_NEW 说明: 帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下(但定义了一个DEBUG符号),DEBUG_NEW为它分配的每个对象记录文件名和行号。然后,在用户使用CMemoryState::DumpAllObjectSince成员函数时,每个以DEBUG_NEW分配的对象分配的地方显示出文件名和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令: #define new DEBUG_NEW 一旦用户插入本指令,预处理程序将在使用new的地方插入DEBUG_NEW,而MFC作其余的工作。但用户编译自己的程序的一个发行版时, DEBUG_NEW便进行简单的new操作,而且不产生文件名和行号消息。 DECLARE_DYNAMIC DECLARE_DYNAMIC(class_name) 说明: 但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件中,然后在全部需要访问词类对象的.CPP文件中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使用RUNTIME_CLASS宏和CObject::IsKindOf函数以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中,那么IMPLEMETN_DYNAMIC必须包含在类工具中。 DECLARE_DYNCREATE DECLARE_DYNCREATE(class_name) 说明: 使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立新对象,例如,但它在串行化过程中从磁盘读一个对象时,文件及视图和框架窗应该支持动态建立,因为框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中,然后在全部需要访问此类对象的.CPP文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中,那么 IMPLEMENT_DYNCREATE必须包含在类工具中。 DECLARE_MESSAGE_MAP DECLARE_MESSAGE_MAP() 说明: 用户程序中的每个CCmdTarget派生类必须提供消息映射以处理消息。在类定义的末尾使用DECLARE_MESSAGE_MAP宏。接着,在定义类成员函数的.CPP文件中,使用BEGIN_MESSAGE_MAP宏,每个用户消息处理函数的宏项下面的列表以及 END_MESSAGE_MAP宏。 注释: 如果在DECLARE_MESSAGE_MAP之后定义任何一个成员,那么必须为他们指定一个新存取类型(公共的,私有的,保护的)。 DECLARE_SERIAL DECLARE_SERIAL(class_name) 说明: DECLARE_SERIAL为一个可以串行化的CObject派生类产生必要的C++标题代码。串行化是把某个对象的内容从一个文件读出和写入一文件。在.H文件中使用DECLARE_SERIAL宏,接着在需要访问此类对象的全部.CPP文件中包含此文件。如果DECLARE_SERIAL包含在类定义中,那么IMPLEMENT_SERIAL必须包含在类工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC, IMPLEMENT_DYCREATE的功能。 END_CATCH END_CATCH 说明: 标识最后的CATCH或AND_CATCH块的末尾。 END_MESSAGE_MAP END_MESSAGE_MAP 说明: 使用END_MESSAGE_MAP宏结束用户的消息映射定义 IMPLEMENT_DYNAMIC IMPLEMENT_DYNAMIC(class_name,base_class_name) 说明: 通过运行时在串行结构中为动态CObject派生类访问类名和位置来产生必要的C++代码。在.CPP文件中使用IMPLEMENT_DYNAMIC宏,接着一次链接结果对象代码 IMPLEMENT_DYNCREATE IMPLEMENT_DYNCREATE(class_name,base_class_name) 说明: 通过DECLARE_DYNCREATE宏来使用IMPLEMENT_DYNCREATE宏,以允许CObject派生类对象在运行时自动建立。主机使用此功能自动建立对象,例如,但它在串行化过程中从磁盘读去一个对象时,他在类工具里加入IMPLEMENT_DYNCREATE宏。若用户使用 DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,那么接着使用RUNTIME_CLASS宏和CObject:: IsKindOf成员函数以在运行时确定对象类。若declare_dyncreate包含在定义中,那么IMPLEMENT_DYNCREATE必须包含在类工具中。 IMPLEMENT_SERIAL IMPLEMENT_SERIAL(class_name,base_class_name,wSchema) 说明: 通过运行时在串行结构中动态CObject派生类访问类名和位置来建立必要的C++代码。在.CPP文件中使用IMPLEMENT_SERIAL宏,然后一次链接结果对象代码。 ON_COMMAND ON_COMMAND(id,memberFxn) 说明: 此宏通过ClassWizard或手工插入一个消息映射。它表明那个函数将从一个命令用户接口(例如一个菜单项或toolbar按钮)处理一个命令消息。当一个命令对象通过指定的ID接受到一个Windows WM_COMMAND消息时,ON_COMMAND将调用成员函数memberFxn处理此消息。在用户的消息映射中,对于每个菜单或加速器命令(必须被映射到一个消息处理函数)应该确实有一个ON_COMMAND宏语句。 ON_CONTROL ON_CONTROL(wNotifyCode,id,memberFxn) 说明: 表明哪个函数将处理一个常规控制表示消息。控制标识消息是那些从一个控制夫发送到母窗口的消息。 ON_MESSAGE ON_MESSAGE(message,memberFxn) 说明: 指明哪个函数将处理一用户定义消息。用户定义消息通常定义在WM_USER到0x7FF范围内。用户定义消息是那些不是标准Windows WM_MESSAGE消息的任何消息。在用户的消息映射中,每个必须被映射到一个消息处理函数。用户定义消息应该有一个ON_MESSAGE宏语句。 ON_REGISTERED_MESSAGE ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn) 说明: Windows的RegisterWindowsMesage函数用于定义一个新窗口消息,此消息保证在整个系统中是唯一的。此宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰符来定义。 ON_UPDATE_COMMAND_UI ON_UPDATE_COMMAND_UI(id,memberFxn) 说明: 此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个用户接口个更改命令消息。在用户的消息映射中,每个用户接口更改命令(比讯被映射到一个消息处理函数)应该有一个ON_UPDATE_COMMAND_UI宏语句。 ON_VBXEVENT ON_VBXEVENT(wNotifyCode,memberFxn) 说明: 此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个来自VBX控制的消息。在用户的消息映射中每个被映射到一消息处理函数的VBX控制消息应该有一个宏语句。 RUNTIME_CLASS RUNTIME_CLASS(class_name) 说明: 使用此宏从c++类民众获取运行时类结构。RUNTIME_CLASS为由class_name指定的类返回一个指针到 CRuntimeClass结构。只有以DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的 CObject派生类才返回到一个CRuntimeClass结构的指针。 THROW THROW(exception_object_pointer) 说明: 派出指定的异常。THROW中断程序的运行,把控制传递给用户程序中的相关的CATCH块。如果用户没有提供CATCH块,那么控制被传递到一个MFC模块,他打印出一个错误并终止运行。 THROW_LAST THROW_LAST() 说明: 此宏允许用户派出一个局部建立的异常。如果用户试图排除一个刚发现的异常,那么一般此异常将溢出并被删除。使用THROW_LAST,此异常被直接传送到下一个CATCH处理程序。 TRACE TRACE(exp) 说明: 把一个格式化字符串送到转储设备,例如,文件或调试监视器,而提供与printf相似的功能。同MS_DOS下C程序的printf一样, TRACE宏是一个在程序运行时跟踪变量值的方便形式。在DEBUG环境中,TRACE宏输出到afxDump。在Release版中他不做任何工作。 注释: 此宏只在MFC的DEBUG版中有效。 TRACE0 TRACE0(exp) 说明: 与TRACE相似,但他把跟踪字符串放在代码段中,而不是DGROUP,因此使用少的DGROUP空间。TRACE0是一组跟踪宏的一个变体,这些宏可用于调试输出。这一组包括TRACE0,TRACE1,TRACE2和TRACE3,这些宏不同在于所取参数的数目不同。TRACE0只取一个格式化字符串并可用于简单文本消息。TRACE1取一格式化字符串加上一个变量——一个将转储的变量。同样,TRACE2,TRACE3分别取2个或3个参数(在格式化字符串之后)。如果用户以便以了应用程序的发行版,那么它只把数据转储到afxDump。 注释: 此宏只在MFC的DEBUG中有效。 TRACE1 TRACE1(exp,param1) 说明: 参见TRACE0 TRACE2 TRACE2(exp,param1,param2) 说明: 参见TRACE0 TRACE3 TRACE3(exp,param1,param2,param3) 说明: TRY TRY 说明: 使用此宏建立一TRY块。一个TRY识别一个可排除异常的代码块。这些异常在随后的CATCH和AND_CATCH块处理。传递是允许的:异常可以传递一个外部TRY块,或者忽略它们或者使用THROW_LAST宏。 VERIFY VERIFY(booleanExpression) 说明: 在MFC的DEBUG版中,VERIFY宏计算它的变量值。 如果结果为0,那么宏打印一个诊断消息并中止程序。如果条件不为0,那么什么工作也不作。 诊断有如下形式: assertion failed in file in line 其中name是源文件的名字,num是在源文件中失败的中止行号。在MFC的Release版中,VERIFY计算表达式值但不打印或中止程序。例如:如果表达式是个函数调用,那么调用成功。 阅读全文... |
| esqm 于12 : 55 发表 已被浏览65次 评论(0) / 引用(1) 加入博采中心 |
| pragma指令简介 |
| 2005年 01月04日 |
-- 选择自 vcforever 的 Blog 在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作. 一. message 参数。 message 其使用方法为: #pragma message("消息文本") 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 格式如: #pragma code_seg( [ [ { push | pop}, ] [ identifier, ] ] [ "segment-name" [, "segment-class" ] ) //将函数存放在.my_data1节中 //r1为标识符,将函数放入.my_data2节中 int main() { 这是一个比较常用的指令,只要在头文件的最开始加入这条指令就能够保证头文件被编译一次 BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。 该指令允许有选择性的修改编译器的警告消息的行为 主要用到的警告表示有如下几个: once:只显示一次(警告/错误等)消息 如果大家对上面的解释不是很理解,可以参考一下下面的例子及说明 在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707) 在使用标准C++进行编程的时候经常会得到很多的警告信息,而这些警告信息都是不必要的提示,所以我们可以使用#pragma warning(disable:4786)来禁止该类型的警告在vc中使用ADO的时候也会得到不必要的警告信息,这个时候我们可以通过#pragma warning(disable:4146)来消除该类型的警告信息 六. pragma comment(...) compiler:将编译器的版本号和名称放入目标文件中,本条注释记录将被编译器忽略 exestr:将commentstring参数放入目标文件中,在链接的时候这个字符串将被放入到可执行文件中,当操作系统加载可执行文件的时候,该参数字符串不会被加载到内存中.但是,该字符串可以被dumpbin之类的程序查找出并打印出来,你可以用这个标识符将版本号码之类的信息嵌入到可 执行文件中! lib:这是一个非常常用的关键字,用来将一个库文件链接到目标文件中常用的lib关键字,可以帮我们连入一个库文件。
你可以在程序中设置下列链接选项 /DEFAULTLIB
user:将一般的注释信息放入目标文件中commentstring参数包含注释的文本信息,这个注释记录将被链接器忽略 |
| esqm 于12 : 48 发表 已被浏览53次 评论(0) / 引用(0) 加入博采中心 |
| 多任务、进程和线程 |
| 2004年 12月20日 |
Windows 95/NT的抢先式多任务 在32位的Windows系统中,采用的是抢先式多任务,这意味着程序对CPU的占用时间是由系统决定的。系统为每个程序分配一定的CPU时间,当程序的运行超过规定时间后,系统就会中断该程序并把CPU控制权转交给别的程序。与协同式多任务不同,这种中断是汇编语言级的。程序不必调用象PeekMessage这样的函数来放弃对CPU的控制权,就可以进行费时的工作,而且不会导致系统的挂起。 进程与线程 在32位的Windows系统中,术语多任务是指系统可以同时运行多个进程,而每个进程也可以同时执行多个线程。 进程就是应用程序的运行实例。每个进程都有自己私有的虚拟地址空间。每个进程都有一个主线程,但可以建立另外的线程。进程中的线程是并行执行的,每个线程占用CPU的时间由系统来划分。 进程就是应用程序的运行实例。每个进程都有自己私有的虚拟地址空间。每个进程都有一个主线程,但可以建立另外的线程。进程中的线程是并行执行的,每个线程占用CPU的时间由系统来划分。可以把线程看成是操作系统分配CPU时间的基本实体。系统不停地在各个线程之间切换,它对线程的中断是汇编语言级的。系统为每一个线程分配一个CPU时间片,某个线程只有在分配的时间片内才有对CPU的控制权。实际上,在PC机中,同一时间只有一个线程在运行。由于系统为每个线程划分的时间片很小(20毫秒左右),所以看上去好象是多个线程在同时运行。 进程中的所有线程共享进程的虚拟地址空间,这意味着所有线程都可以访问进程的全局变量和资源。这一方面为编程带来了方便,但另一方面也容易造成冲突。 虽然在进程中进行费时的工作不会导致系统的挂起,但这会导致进程本身的挂起。所以,如果进程既要进行长期的工作,又要响应用户的输入,那么它可以启动一个线程来专门负责费时的工作,而主线程仍然可以与用户进行交互。 线程的创建和终止 线程分用户界面线程和工作者线程两种。用户界面线程拥有自己的消息泵来处理界面消息,可以与用户进行交互。工作者线程没有消息泵,一般用来完成后台工作。 MFC应用程序的线程由对象CWinThread表示。在多数情况下,程序不需要自己创建CWinThread对象。调用AfxBeginThread函数时会自动创建一个CWinThread对象。 应用程序的线程由对象CWinThread表示。在多数情况下,程序不需要自己创建CWinThread对象。调用AfxBeginThread函数时会自动创建一个CWinThread对象。 当发生下列事件之一时,线程被终止: 线程调用ExitThread。 线程函数返回,即线程隐含调用了ExitThread。 ExitThread。ExitProcess被进程的任一线程显示或隐含调用.用线程的句柄调用 TerminateThread。 用进程句柄调用TerminateProcess。 TerminateProcess。 线程函数返回,即线程隐含调用了ExitThread。 线程的同步 由于同一进程的所有线程共享进程的虚拟地址空间,并且线程的中断是汇编语言级的,所以可能会发生两个线程同时访问同一个对象(包括全局变量、共享资源、API函数和MFC对象等)的情况,这有可能导致程序错误。例如,如果一个线程在未完成对某一大尺寸全局变量的读操作时,另一个线程又对该变量进行了写操作,那么第一个线程读入的变量值可能是一种修改过程中的不稳定值。 属于不同进程的线程在同时访问同一内存区域或共享资源时,也会存在同样的问题。 因此,在多线程应用程序中,常常需要采取一些措施来同步线程的执行。需要同步的情况包括以下几种: 在多个线程同时访问同一对象时,可能产生错误。例如,如果当一个线程正在读取一个至关重要的共享缓冲区时,另一个线程向该缓冲区写入数据,那么程序的运行结果就可能出错。程序应该尽量避免多个线程同时访问同一个缓冲区或系统资源。 在Windows 95环境下编写多线程应用程序还需要考虑重入问题。Windows NT是真正的32位操作系统,它解决了系统重入问题。而Windows 95由于继承了Windows 3.x的部分16位代码,没能够解决重入问题。这意味着在Windows 95中两个线程不能同时执行某个系统功能,否则有可能造成程序错误,甚至会造成系统崩溃。应用程序应该尽量避免发生两个以上的线程同时调用同一个Windows API函数的情况。 由于大小和性能方面的原因,MFC对象在对象级不是线程安全的,只有在类级才是。也就是说,两个线程可以安全地使用两个不同的CString对象,但同时使用同一个CString对象就可能产生问题。如果必须使用同一个对象,那么应该采取适当的同步措施。 多个线程之间需要协调运行。例如,如果第二个线程需要等待第一个线程完成到某一步时才能运行,那么该线程应该暂时挂起以减少对CPU的占用时间,提高程序的执行效率。当第一个线程完成了相应的步骤后,应该发出某种信号来激活第二个线程。 等待函数 Win32 API提供了一组能使线程阻塞其自身执行的等待函数。这些函数只有在作为其参数的一个或多个同步对象(见下小节)产生信号时才会返回。在超过规定的等待时间后,不管有无信号,函数也都会返回。在等待函数未返回时,线程处于等待状态,此时线程只消耗很少的CPU时间。 使用等待函数即可以保证线程的同步,又可以提高程序的运行效率。最常用的等待函数是WaitForSingleObject,该函数的声明为: DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); 同步对象 同步对象用来协调多线程的执行,它可以被多个线程共享。线程的等待函数用同步对象的句柄作为参数,同步对象应该是所有要使用的线程都能访问到的。同步对象的状态要么是有信号的,要么是无信号的。同步对象主要有三种:事件、mutex和信号灯。 事件对象(Event)是最简单的同步对象,它包括有信号和无信号两种状态。在线程访问某一资源之前,也许需要等待某一事件的发生,这时用事件对象最合适。例如,只有在通信端口缓冲区收到数据后,监视线程才被激活。 事件对象是用CreateEvent函数建立的。该函数可以指定事件对象的种类和事件的初始状态。如果是手工重置事件,那么它总是保持有信号状态,直到用ResetEvent函数重置成无信号的事件。如果是自动重置事件,那么它的状态在单个等待线程释放后会自动变为无信号的。用SetEvent可以把事件对象设置成有信号状态。在建立事件时,可以为对象起个名字,这样其它进程中的线程可以用OpenEvent函数打开指定名字的事件对象句柄。 mutex对象的状态在它不被任何线程拥有时是有信号的,而当它被拥有时则是无信号的。mutex对象很适合用来协调多个线程对共享资源的互斥访问(mutually exclusive)。 线程用CreateMutex函数来建立mutex对象,在建立mutex时,可以为对象起个名字,这样其它进程中的线程可以用OpenMutex函数打开指定名字的mutex对象句柄。在完成对共享资源的访问后,线程可以调用ReleaseMutex来释放mutex,以便让别的线程能访问共享资源。如果线程终止而不释放mutex,则认为该mutex被废弃。 信号灯对象维护一个从0开始的计数,在计数值大于0时对象是有信号的,而在计数值为0时则是无信号的。信号灯对象可用来限制对共享资源进行访问的线程数量。线程用CreateSemaphore函数来建立信号灯对象,在调用该函数时,可以指定对象的初始计数和最大计数。在建立信号灯时也可以为对象起个名字,别的进程中的线程可以用OpenSemaphore函数打开指定名字的信号灯句柄。 一般把信号灯的初始计数设置成最大值。每次当信号灯有信号使等待函数返回时,信号灯计数就会减1,而调用ReleaseSemaphore可以增加信号灯的计数。计数值越小就表明访问共享资源的程序越多。 除了上述三种同步对象外,表12.3中的对象也可用于同步。另外,有时可以用文件或通信设备作为同步对象使用。 当对象不再使用时,应该用CloseHandle函数关闭对象句柄。 关键节和互锁变量访问 关键节(Critical Seciton)与mutex的功能类似,但它只能由同一进程中的线程使用。关键节可以防止共享资源被同时访问。 进程负责为关键节分配内存空间,关键节实际上是一个CRITICAL_SECTION型的变量,它一次只能被一个线程拥有。在线程使用关键节之前,必须调用InitializeCriticalSection函数将其初始化。如果线程中有一段关键的代码不希望被别的线程中断,那么可以调用EnterCriticalSection函数来申请关键节的所有权,在运行完关键代码后再用LeaveCriticalSection函数来释放所有权。如果在调用EnterCriticalSection时关键节对象已被另一个线程拥有,那么该函数将无限期等待所有权。 利用互锁变量可以建立简单有效的同步机制。使用函数InterlockedIncrement和InterlockedDecrement可以增加或减少多个线程共享的一个32位变量的值,并且可以检查结果是否为0。线程不必担心会被其它线程中断而导致错误。如果变量位于共享内存中,那么不同进程中的线程也可以使用这种机制。 串行通信与重叠I/O Win 32系统为串行通信提供了全新的服务。传统的OpenComm、ReadComm、WriteComm、CloseComm等函数已经过时,WM_COMMNOTIFY消息也消失了。取而代之的是文件I/O函数提供的打开和关闭通信资源句柄及读写操作的基本接口。 新的文件I/O函数(CreateFile、ReadFile、WriteFile等)支持重叠式输入输出,这使得线程可以从费时的I/O操作中解放出来,从而极大地提高了程序的运行效率。 串行口的打开和关闭 Win32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台,都是用API函数CreateFile来打开或创建的。 串行口的初始化 在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。在查询或配置置串行口的属性时,都要用DCB结构来作为缓冲区。 调用GetCommState函数可以获得串口的配置,该函数把当前配置填充到一个DCB结构中。一般在用CreateFile打开串行口后,可以调用GetCommState函数来获取串行口的初始配置。要修改串行口的配置,应该先修改DCB结构,然后再调用SetCommState函数用指定的DCB结构来设置串行口。 除了在DCB中的设置外,程序一般还需要设置I/O缓冲区的大小和超时。Windows用I/O缓冲区来暂存串行口输入和输出的数据,如果通信的速率较高,则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。 在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。 有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读/写操作的超时. 重叠I/O 在用ReadFile和WriteFile读写串行口时,既可以同步执行,也可以重叠(异步)执行。在同步执行时,函数直到操作完成后才返回。这意味着在同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,调用的函数也会立即返回。费时的I/O操作在后台进行,这样线程就可以干别的事情。例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。"重叠"一词的含义就在于此。 ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。 ReadFile和WriteFile函数是否为执行重叠操作是由CreateFile函数决定的。如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的读写操作就是重叠的,如果未指定重叠标志,则读写操作是同步的. |
| esqm 于22 : 39 发表 已被浏览249次 评论(2) / 引用(5) 加入博采中心 |
| COM组件调入大致过程 |
| 2004年 11月22日 |
|
| esqm 于17 : 27 发表 已被浏览181次 评论(2) / 引用(12) 加入博采中心 |
| MIDL(microsoft接口定义语言)基础 |
| 2004年 11月21日 |
所有数据、方法、接口、类和库的特性都由属性信息来描述。属性信息中由括号括起来,作为它们描述的对象的前缀。 [in] : 告诉MIDL编译器生成代码时,只是把从客户到对象的数据列集,没必要把同样的数据列集送回给客户 [out] : 让一段数据从对象返回到客户。 cpp_quote("/////////////////////////////////////////////") HRESULT QueryInterface( [in] REFIID iid, ULONG AddRef(); [UUID] : 这是IOcr接口静态的和唯一的IID,它是一个在时间上和空间上独一无二的机器生成数字。 [local] : 告诉MIDL编译器,不要生成接口代理和存根。 [pointer_default()] : 设定了所有还没有显示限定的嵌入式指针(embedded pointer)的默认指针属性信息。嵌入式指针(embedded pointer)包括结构体(structrue)、联合体(union)、数组(array)的成员指针. unique属性信息:1)[ref]指针是引用指针(reference pointer),不能为空。 指向同一个数据,那个数据的两份相同的副本会被送往远程对象。 cpp_quote:指导MIDL编译器将限定了的字符串转换成生成的头文件。具体来说,这四行会在MIDL编译器生成的头文件中做出C++的注释。 [iid_is()] : 这是一个指针属性,它与[ptr][ref][unique]相似,只适用于指针。iid_is(riid)属性列集器关心,实际上,存根需要准确地知道正在调度的接口指针(riid,某种IID) [size_is()] : 显示地告诉列集器,指针实际指向一些字节的块。列集器根据这个块的大小分配内存。 [string] : 提示列集器:修饰的本参数是一个字符串,是以null终止的。 |
| esqm 于21 : 11 发表 已被浏览132次 评论(0) / 引用(8) 加入博采中心 |
| C++类型转换操作符(cast operator) |
| 2004年 11月21日 |
dynamic_cast 例如: |
| esqm 于19 : 38 发表 已被浏览115次 评论(0) / 引用(9) 加入博采中心 |
| Com的功能和服务 |
| 2004年 11月21日 |
COM :Component Object Model 组件对象模型。 Com的功能和服务: 1、位置透明性 3、安全性 5、生存期支持和动态发现 6、二进制互操作性 7、连接管理 8、并发管理 9、重用 10、接口储藏库 13、动态调用 14、事件 |
本文详细探讨了Visual C++中的宏定义,包括其在编译器优化、异常处理、类设计以及Windows和MFC应用程序中的关键应用。通过实例解析,揭示了宏在命令行参数处理中的灵活使用和潜在陷阱,帮助读者深化对VC宏定义的理解。

5741

被折叠的 条评论
为什么被折叠?



