C++语言和库支持

5.3 C++语言和库支持
在这节中描述了VxWorks C++执行的某些特殊方面。要学习更多的关于C++语言和标准库请参考任何C++标准(推荐《The C++ Programming Language, Third Edition》)。
5.3.1 语言特征
我们支持许多但并不是所有的被ANSI认可的C++标准的新特性。Tornado 2.0支持异常处理和运行时类型信息,也就是增强了的模板支持。我们不支持名字空间特性,尽管编译器将接受(和忽略)对std名字空间的引用。
异常处理
缺省地我们的C++编译器支持多线程安全的异常处理。为了取消异常处理,使用编译器标志-fno-exceptions。
使用异常
你或许会写代码来处理C++模块的异常。举个例子,对new的调用会检查返回的指针是否是失败值0。如果你担心在这个版本中增加的异常处理将不能正确编译你的代码,你应该坚持下面的简单规则:
.使用new(不抛出异常)
.在你的Iostream对象中不要直接地(explicitly)打开异常。
.不要使用字符串对象或者把它们封装到块"try {} catch (...) {}" 中。

这些规则来源于下面的信息:
.GNU Iostream不会抛出异常除非在构建库时定义了IO_THROW并且对使用中的特定的Iostream对象打开了异常。缺省是没有异常。异常必须明确地开启需要抛出的每个输入输出状态标志。
.对类basic_string的某些方法,STL不会抛出异常。
异常处理的开销
为了支持对在堆栈展开过程中产生的自动对象的消除,编译器必须把一段固定的代码连同析构函数插入到创建自动(基于堆栈)对象的函数中。
下面的是在PowerPC 604目标(BSP mv2604)上测量的异常处理开销;是按执行的指令数来计数。1235条指令用来执行"throw 1"和有关联的"catch (...)".这里的14条额外指令同析构函数一起注册/注销自动变量和临时对象;29条额外指令在非内联函数中使用;最后,在遇到第一个异常处理结构(construct)(try, catch, throw或注册的自动变量或临时对象),执行947条额外指令。
first time normal case
void test() { // 3+29 3+29
throw 1; // 1235 1235 total time to printf
}

void doit() { // 3+29+947 3+29
try { // 22 22
test(); // 1 1
} catch (...) {
printf("Hi/n");
}
}

struct A { ~A( ) { } };

void local_<I>var</I> ( ) { // 3+29
A a; // 14
} // 4
-fno-exceptions能够用来关掉异常处理。这样做将减少返回到传统(classical)C++的开销。
未处理的异常
按标准要求,一个没有捕获的异常最后将导致调用terminate().这个函数缺省的行为是挂起任务和把警告消息发到控制台。你也可以通过调用set_terminate()(定义在头文件exception中)安装自己的终端处理。
运行时类型信息(RTTI)
这个特性缺省是开启的,它只增加很小的开销到任何包含带有虚拟函数的类的C++程序。如果你不需要这个特性,可以使用-fno-rtti关掉它。
5.3.2 标准模板库(STL)
STL由小的运行时组件(通过选择INCLUDE_CPLUS_STL将其配置到你的内核中)和头文件集合组成。
STL行为(port)在类的级别上VxWorks线程安全的。这意味着如果两个任务想要使用同样的容器对象(container object),客户端不得不提供明确的锁定(locking).(例如,使用旗语(semaphores)就需要这样做,细节参见2.4.3 Semaphores)然而两个同为STL容器类的不同对象可同时存取。
Iostream库
通过选择包含在项目工具VxWorks视图里的INCLUDE_CPLUS_IOSTREAMS把这个库配置到VxWorks中;参见5.2.4配置常量。
Iostream库头文件在VxWorks头文件目录中,<安装路径>/target/h。为了使用这个库,在应用程序的相应模块里,在头文件vxWorks.h后包括一个或多个头文件。最频繁使用的头文件是iostream.h,但是其他的头文件也会用到,具体信息参看C++参考例如Stroustrup。
标准的Iostream对象(cin, cout, cerr和clog)是全局的,那就是说,对于任何给定的任务他们不是私有的。它们被正确初始化而不管任务或模块引用它们的数目,它们也可安全的交叉使用在多任务中,尽管这些任务有着stdin,stdout和stderr的相同定义。然而当不同的任务有不同的标准输入输出文件描述符时使用它们是不安全的;在这种情况下,对于互斥的处理在于应用程序。
通过创建新的同一个类的Iostream对象做为标准的Iostream对象来模仿私有标准Iostream对象的作用(例如,cin是一个istream_withassign),并分配给它一个新的filebuf对象,该对象依赖合适的文件描述符。这个新的filebuf和Iostream对象对调用它的任务是私有的,并确保没有其它任务能够偶然地误用它们。
ostream my_out (new filebuf (1)); /* 1 == STDOUT */
istream my_in (new filebuf (0), &my_out); /* 0 == STDIN;
* 依赖 my_out */
关于Iostreams库的完全细节,参见在线手册《The GNU C++ Iostream Library》。
字符串和复数类
这些类是新的标准C++库的一部分。通过选择包含在项目工具VxWorks视图里的INCLUDE_CPLUS_STRING和INCLUDE_CPLUS_COMPLEX可以把它们配置到内核中。你可以通过选择INCLUDE_CPLUS_STRING_IO和INCLUDE_CPLUS_COMPLEX_IO包括这些类的I/O功能。
注意:Tornado 2.0 C++没有包括对多字节字符串的支持.Wind基类中tools.h++的一部分包含这样的类.

5.5 Wind基类
Wind基类包括两个库:
.VxWorks Wrapper类库
.来自Rogue Wave Software的Tools.h++库
VxWorks Wrapper类库提供了瘦(thin)C++接口给几个标准VxWorks模块。来自Rogue Wave Software的Tools.h++基类库支持各种C++功能。
注意:为了防止VxWorks库和Rogue Wave库的从属冲突(dependency conflicts),所有的VxWorks库,包括VxWorks Wrapper类库,应该在所有包括Tools.h++库的Rogue Wave库前被包括。
5.5.1 VxWorks Wrapper类库
在这个库中的类被称为wrapper类因为对一部分标准的VxWorks函数,每个类封装或隐藏了(encapsulates, or wraps)接口。选择包含在项目工具VxWorks视图里的INCLUDE_CPLUS_VXW把这个库配置到VxWorks中,参见5.2.4配置常量。
VxWorks Wrapper类库头文件在标准的VxWorks头文件目录中,<安装路径>/target/h。这些类和它们相应的头文件在表5-1中列出。为了使用这些类,在应用程序的适当模块中包含相应头文件。
表5-1
--------------------------------------------------------------------------------------
头文件 描述
--------------------------------------------------------------------------------------
vxwLoadLib.h 对象模块的加载器和卸载器(wraps loadLib, unldLib, moduleLib)
vxwLstLib.h 连接的链表(wraps lstLib)
vxwMemPartLib.h 内存分配(wraps memLib)
vxwMsgQLib.h 消息队列(wraps msgQLib)
vxwRngLib.h 环形缓冲区(wraps rngLib)
vxwSemLib.h 旗语(wraps semLib)
vxwSmLib.h 共享内存对象(增加对共享内存旗语,消息队列,内存分配)
vxwSymLib.h Symbol表(wraps symLib)
vxwTaskLib.h 任务(wraps taskLib, envLib, errnoLib, sigLib, and task<I>var</I>Lib)
vxwWdLib.h Watchdog定时器(wraps wdLib)
--------------------------------------------------------------------------------------
VxWorks Wrapper类设计为提供对面向对象的VxWorks模块的C++语言绑定,但是在使用前就进行了C绑定.图5-1显示了所有的VxWorks Wrapper类的继承关系。这些类的命名与VxWorks函数一致。例如,VXWMsgQ是消息队列类,提供msgQLib的C++接口。

注意:类VXWError和VXWIdObject是VxWorks Wrapper类内部使用的,把它们列在图5-1仅仅为了完整。这两个类并不会在应用程序中直接使用。
图5-1:Wrapper类的继承

例5-3:Watchdog定时器
为了举例说明wrapper类提供的对VxWorks模块的C++语言绑定,下面的例子用watchdog定时器类VXWWd来说明这个方法.关于Watchdog定时器的一般信息参见2.6 Watchdog定时器。
/* Create a watchdog timer and set it to go off in 3 seconds. */

/* includes */

#include "vxWorks.h"
#include "logLib.h"
#include "vxwWdLib.h"

/* defines */

#define SECONDS (3)

task (void)
{
/* Create watchdog */
[1] VXWWd myWatchDog;

/* Set timer to go off in SECONDS - printing a message to stdout */

[2] if (myWatchDog.start (sysClkRateGet( ) * SECONDS, logMsg,
int ("Watchdog timer just expired/n")) == ERROR)
return (ERROR);

while (TIMER_NEEDED)
{
/* ... */
}
[3] }
值得注意的一个不同于C接口是wrapper类允许把watchdog定时器作为对象操作而不是通过对象ID来操作。[1]行创建和命名一个watchdog定时器:C++自动调用VXWWd构造函数,隐式调用C函数wdCreate()来创建watchdog定时器。
[2]行举例说明了如何使用来自wrapper类的方法。例子为了使类VXWWd的myWatchDog实例调用定时器而调用方法start()来实现。因为这个方法在指定的对象上调用,所以方法start()的参数列表不需要指明那个定时器开始。(不像wdStart(),相应的C函数).
最后,因为myWatchDog是本地对象,在从函数task()退出的[3]行上自动调用VXWWd watchdog类中的析构函数。这样隐式调用析构函数释放watchdog对象,即使从系统定时器队列中移除的定时器仍然运行。因而,对于声明在堆栈上的对象,没有必要调用同C函数wdDelete()相当的函数。(然而,如果一个对象是用操作符new动态创建的,那么一旦应用程序不再需要这个对象你必须显示的用操作符delete来删除它。)
关于wrapper类和每个wrapper类的函数的细节,参见《VxWorks Reference Manual》。
5.5.2 Tools.h++库
Tools.h++是来自Rogue Wave Software的工业标准基类库,它支持如下功能:
.完整的collection类集合
.基于类的模板
.存储工具
.文件类和file space manager
.B树硬盘恢复
.多线程安全
.多字节和宽字符字符串
.局部字符串整理
.对时间,日期的解析和格式化
.支持多种时间区域
.支持局部消息
.局部I/O流
选择包含在项目工具VxWorks视图里的INCLUDE_CPLUS_TOOLS把这个库配置到VxWorks中,参见5.2.4配置常量。
Tools.h++类库头文件在标准的VxWorks头文件目录中,<安装路径>/target/h/rw。为了使用这个库,在语句#include "vxWorks.h"后#include一个或多个它们的头文件,然后在这些#include语句后面是所有其它的VxWorks库的头文件。关于这个库的一系列的头文件和细节参见《Rogue Wave's Tools.h++ Introduction and Reference Manual》.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值