??xml version="1.0" encoding="utf-8" standalone="yes"?> 在过ȝ十年中,DirectX已经Ex成ؓ了Microsoft Windowsq_上进行游戏开发的首选API。每一代的DirectX都带来对新的囑ŞgҎ的支持Q因此每ơ都能帮助游戏开发者们q出惊h的一步?/p>
微YDirectX API(Application Programming interface :应用E序界面) 最早发布于1995q_其设计目标是为Windowsq_软g开发h员提供一个更便的针对多媒体和游戏应用~程的标准接口?/p>
在DirectX出台Q开发者针寚w频、视频等的操作必d于硬件进行,——当ӞZOpenGL能够在很大程序上减轻工作量,但OpenGL获得的支持显然远q不够。——而显卡、声卡等的品种cM多,要编写一ƾ能q行在所有^C的游戏简直是一件噩梦般的工作?/p>
通过提供一pd的针对多媒体应用的APIQ如囑Ş(包括2D?D应用)、音频或输入讑֤{,DirectX提供了一整套的多媒体接口ҎQ这可以让开发者根据API~写相应的Y件程序,而不必考虑具体的硬Ӟg的差别性显得无重,~程人员得以更有效率的开发各U多媒体、游戏Y件?/p>
当然QDirectX的发展ƈ不是一帆风的Q最初的版本q谈不上E_。
做完之后整理Qlua, luabind 以sdk 形式l织好,我是q样l织:
\luabind_build\sdk\luabind\include
\luabind_build\sdk\luabind\msvc-9.0-sp1\lib
\luabind_build\sdk\lua\include
\luabind_build\sdk\lua\msvc-9.0-sp1\lib
q样Q把sdk中的东东保存一份,方便以后使用。写一个MFC程序测?br>
2 //mfc class function
3 void CMFC_LuaDlg::SetEditText(const char* text)
4 {
5 Edit_1.SetWindowText(text);
6 UpdateData(FALSE);
7 }
8 //register
9 luabind::module(L)
10 [
11 luabind::class_<CMFC_LuaDlg>("mfc_dlg")
12 .def"set_text",&CMFC_LuaDlg::SetEditText)
13 ];
14 //load lua file
15 if (0==luaL_dofile(L,filepath))
16 {
17 ret=true;
18 }
19 //run lua function
20 luabind::call_function<void>(L,"update_text",dlg);
21
2 dlg:set_text("你好Q欢q来到lua 脚本世界")
3 end
]]>
2 Data* FindData();
3 void GetData(Data* dataPtr)
4 {
5 dataPtr=FindData();
6 }
7 Data* data=NULL;
8 GetData(data);
9 data->somefunction();
2 class B;
3 A const * GetA();
4 B const * GetB();
5 template<typename T>
6 int GetSpecialValue(T* classPtr)
7 {
8 return 3721;
9 }
10
11 template<>
12 int GetSpecialValue<>(A* classPtr)
13 {
14 return 37;
15 }
16 template<>
17 int GetSpecialValue<>(B* classPtr)
18 {
19 return 21;
20 }
21 A const * classPtr=GetA();
22 int ret=GetSpecialValue(classPtr);
23 cout<<ret<<endl; //out 3721! why not 37?
24
25
26
2 4 {
3 5 dataPtr=FindData();
4 6 }
2 int GetSpecialValue(T const* classPtr)
3 {
4 return 3721;
5 }
6
7 template<>
8 int GetSpecialValue<>(A const* classPtr)
9 {
10 return 37;
11 }
12 template<>
13 int GetSpecialValue<>(B const* classPtr)
14 {
15 return 21;
16 }
]]>
]]>
]]>
版本
操作pȝ
发布日期
DirectX 1.0
Windows 95a
9/30/95
DirectX 2.0/2.0a
Windows 95OSR2/NT4.0
6/5/96
DirectX 3.0/3.0a
Windows NT 4.0 SP3
9/15/96
DirectX 4.0
未发?/td>
DirectX 5.0
Windows NT 4.0/Beta for NT 5.0
7/16/97
DirectX 5.1
Windows 95/98/NT4.0
12/1/97
DirectX 5.2
Windows 95
5/5/98
DirectX 6.0
Windows 98/NT4.0
8/7/98
DirectX 6.1
Windows 95/98/98SE
2/3/99
DirectX 7.0
Windows 95/98/98SE/2000
9/22/99
DirectX 7.0a
Windows 95/98/98SE/2000
9/99
DirectX 7.1
Windows 95/98/98SE/ME/2000
9/16/99
DirectX 8.0/8.0a
Windows 95/98/98SE/ME/2000
9/30/2000
DirectX 8.1
Windows 95/98/98SE/ME/2000/XP
11/12/01
DirectX 9
Shader Model 2.0Windows 95/98/98SE/ME/2000/XP
12/19/2002
DirectX 9
Shader Model 2.0bWindows 98/98SE/ME/2000/XP
8/13/2003
DirectX 9
Shader Model 3.0Windows 98/98SE/ME/2000/XP
8/9/2004
DirectX中应用在3D囑Ş斚w的特定DirectX API即Direct3DQ这也是DirectX中最重要的部分。不q,DirectX 3D得到q泛应用是在DirectX 6.0之后Q?/p>
DirectX 6.0Q加入了双线性过滤、三U性过滤等优化3D囑փ质量的技术,加入环境影射凹凸贴图Q3D游戏的画面更h真实感?/p>
DirectX 7.0Q最大的特色是支持了T&LQ中文名U是“坐标转换和光?#8221;Q?D游戏中坐标和灯光的{换工作从此由CPU转交l了GPUQ比DX6.1性能提升20%。这也成׃nVIDIA GeForce 256与ATi Radeon 256的辉煌,?DFXd退出市场竞争?/p>
DirectX 7.0aQ增Z力反馈游戏控制设备的性能和兼Ҏ?/p>
DirectX 7.1Q与Windows Millennium一同发布?/p>
DirectX 8.0/8.0aQ支持Shader Model 1.0?.1Q从此在昑֍中引入可~程像素着色器(Pixel Shaders)和顶点着色器(Vertex Shaders)的概念,同时应用在Xbox游戏Z。同gT&L仅仅实现的固定光p{换相比,VS和PS单元的灵zL更大,它GPU真正成ؓ了可~程的处理器?/p>
DirectX 8.1Q?Pixel Shader升?.2?.3?.4版,可以支持最高每旉28指o执行Q其?.4版当时仅ATi Radeon 8500昑֍支持?/p>
DirectX 9.0 Shader Model 2.0Q?SM2.0的shader性能更强Q支持最?6指o的pixel shader长度Q同时DirectPlay和一些音频方面也有大q提升?/p>
DirectX 9.0 Pixel Shader 2.0bQ?ATI Radeon X600/700/800pd昑֍首先采纳Q开始支持更多指?最?536)和更多时寄存器(32相比之前?2)Q同时还加入新的贴面寄存?facing register)和几何实?geometry instancing)的支持?/p>
DirectX 9.0 Shader Model 3.0Q支持更多指令,支持指o的流量控制和动态分支,从而得编Eh员可以在shaders中加入@环操作,使得~程更加ҎQ首ơ被Geforce 6800昑֍采用?/p>
从DirectX的发展史中我们可以看刎ͼ微Y?D API和硬件一同发展,新硬件带来新的DXҎ,新的DXҎ加速硬件的发展Q在DirectX10上面Q又是一?D囑Ş发展的新境界?/p>
DirectX之所以在q大的开发者中行Q是得益于它的简单易用和丰富的功能特性。然而,DirectX一直被一个主要的问题所困扰Q那是高CPU负蝲?/p>
在图形编EAPI出现之前Q?D应用E序直接向图形硬件发送命令来完成囑Ş的绘制工作。虽然这样开发工作比较繁重,但硬件效率则能在很大E度上得C证?/p>
而如DirectX和OpenGLq样的图形API则是通过在图形硬件和应用E序之间架v了一个中间层Q这P应用E序可以使用l一的图形编E代码来完成对底层硬件的操作Q将E序员们从与大量的图形硬件交互的恶梦中解救出来。但是,q也造成了每ơDirectX从应用程序那里接收到一条命令时Q就必须先对q条命oq行分析和处理,再向囑Şg发送相对应的硬件命令。由于这个分析和处理的过E由CPU完成Q造成了每一?Dl图命o都会带来CPU的负载?/p>
从技术角度,q种CPU负蝲l?D图象带来两个负面影响Q首先,限制了画面中可以同时l制的物体数量;其次Q限制了可以在一个场景中使用的独立的Ҏ的数量。这׃得游戏画面中的细节数量受C很大的限Ӟ而图像具有真实感的主要要求便是丰富的l节?/p>
DirectX 10的主要优势便是最大程度地降低了CPU负蝲Q主要通过三个途径来达到这个目的:W一Q修改API核心Q得绘制物体和切换材质Ҏ时的消耗降低,提高l图效率Q第二,引入新的机制Q降低图形运操作对CPU的依赖性,使更多的q算在GPU中完成;W三Q大量的物体可以通过调用单条DirectXl制命oq行扚wl制?/p>
下面我们来仔细的看一下这三种方式Q?/p>
提高l图效率
在DirectX 10中,对上代DirectX版本中三l数据和l制命o的验证过E进行了很大E度的修攏V所谓三l数据和命o的验证,是指在DirectXl制囑Ş之前Q对传给它的囑Ş数据和绘制命令进行格式和数据完整性的查,以保证它们被送到囑Şg时不会导致硬件出问题Q这是很必要的一步操作,但是不幸的是q会带来很大的性能开销?/p>
从上表我们可以很Ҏ的看出,在DirectX 9中,每次l制一帧画面之前,都会对即用的相关数据q行一ơ验证。而DirectX 10中,仅当q些数据被创建后验证一ơ。这很明显是可以大大提高游戏q行中的效率的?/p>
降低囑Şq算对CPU的依?/strong>
在降低图形运对CPU的依赖方面,DirectX 10 引入的三个重要机制就是:U理阵列(texture arrays)、绘刉?(predicated draw)和流式输?stream out)。不要被q三个晦涩的名词吓倒,实际上它们是三个不难理解的机制?/p>
U理阵列 传统的DirectX在多张纹理中q行切换的操作是U很lCPU带来很大压力的操作,因ؓ每切换一ơ,都要调用一ơDirectX的API函数。而每l制一个用新U理的物体,pq行一ơ这L切换操作Q有时ؓ了实现特D的材质ҎQ绘制一个物体时可能p切换好几ơ纹理,开销很大?/p>
所以,之前游戏中经怼出现大量的纹理拼合到一张大的纹理中Q通过l不同的三维物体分配q张大纹理的不同局部的方式Q以期减纹理切换,提高游戏q行效率。这U方式实现v来相当复杂,而且DirectX 9中对U理的尺寸的限制?048×4048像素Q也是_如果要容下更多的纹理块Q可能就得加载很多张q样的大U理?/p>
DirectX 10引入的新的纹理阵列机构,允许在一个由昑֍l护的阵列中容纳512张单独的U理Q而且Q在shaderE序中可以用一条新的指令来获取q个阵列中的L一张纹理。而这Ushader指o是运行在GPU中的Q这P把原来要消耗很多CPU旉的纹理切换工作轻村֜转给了GPU。由于纹理一般是直接攑֜昑֭中的Q因此以q样的方式,工作交与和昑֭一同位于显卡上的GPU来完成更有效率。如今,在DirectX 10中,只要一开始设|好U理阵列中的U理Q然后每ơ绘制一个物体时为它指定一个纹理的索引Pq同物体三维数据一起传递到shader中,可以放心的让GPU来给物体选纹理了?/p>
l制预测 在一般的三维场景里,很多物体都是完全被别的物体挡在后面的。这时候如果要昑֍l制q些物体是白费力气。尽高U的GPU可以通过g法场景画面中被挡住的像素(注意是像?预先剔除Q但是仍然会有很多不应进行的多余q算。例如,一个完全被挡住的复杂的角色模型Q它的n上可能有几千个顶点,需要做复杂的骨骼皮肤动d理、顶点光照运等{,然而,GPU是在处理完这些顶点之后,q要把这个角色模型一个像素一个像素地d画面中时Q才开始判断每个像素是否需要画Q而当所有的像素都被剔除了时Q之前做的顶点处理也全白费了。在DirectX 10中的l制预测便正是针对这U情늚解决Q简a之,l制预测通过用一个可以代表某个复杂物体的单物体来判断q个物体是否被全部挡住了Q例如用一个可以罩住刚才那个角色的大盒子,当绘制这个盒子时Q如果发现所有的像素都被屏蔽掉了Q也x说这个盒子肯定完全看不见Q那么,里面的角色绘制包括骨骼皮肤运等之类的操作便完成不必q行。而一个盒子顶多有八个点Q相比处理几千个点Q开销得多?/p>
另外Q以前这个步骤中有些真运也需CPU完成的,在DirectX 10中,已经完全交由GPU来做Q这也可以在一定程度上减轻CPU的压力?br>数据式输出 数据式输出也是DirectX 10的重要特性,它允许GPU上的Vertex shader或Geometry shader向显存中d数据Q而这在以往的vertex shader中是不可能的?/p>
在之前的DirectX版本中,vertex shader只能d昑֭中已有的点数据Q而DirectX 10中引入的新的Geometry shaderQ不但能d昑֭中的点数据、几?炏V线Dc三角Ş)数据Q还可以生成新的几何数据攑֛昑֭?/p>
扚wl制
在DirectX 9中,Ҏ染状态的理一直是个十分信赖于CPUq算能力的操作。所谓渲染状态,是指昑֍q行一ơ绘制操作时所需要设|的各种数据和参数。例如,要绘制一个h物角Ԍ需要先讄他的几何模型数据的数据格式、纹理过滤模式、半透明混合模式{等Q每讄一,都要调用一ơDirectX APIQ占用大量CPU旉Q极大的U束了渲染的性能?/p>
Z使这些操作能够批量的q行QDirectX 10中引入了两个新的l构——状态对?state object)和常量缓?constant buffers)?/p>
状态对象就是将以前的零散状态按照功能归lؓ几个整体Q这P当要讄一pd相关状态时Q无需为每一个状态来调用一ơDirectX API,只需要调用一ơ将q些状态统l设|到昑֍中去?/p>
而常量缓冲是另一个十分有意义的机制。在l制模型前的准备工作中,渲染状态的讄只是一部分。还是拿l制人物角色来说Q能照亮q个人的光源的颜艌Ӏ位|、类型、范围等{,都要提前讄昑֍Qؓ了通过骨骼来带动他的皮肤做出姿势,q要讄骨骼的位|信息等{,而这些东西主要都是通过GPU中的帔R寄存?constant registers)来传递给它的。每个常量寄存器可以存储一?l的点型向?卛_个QҎ)。常量寄存器是游戏程序向GPU输入游戏场景中数据的重要途径?/p>
在DirectX 9中,q种帔R寄存器的数量是十分有限的Q而且每次更新一个寄存器Q都需要调用一ơDirectX API函数。DirectX 10通过使用帔R~冲(constant buffer)q种l构Q在每个constant buffer中都可以容纳4096个常量,而且只需调用一ơAPI可以更C大批帔R?/p>
比如_在以前的DirectX版本中,如果E序惛_场景里画很多的树木和杂草Q可以采用一个类g“克隆”的方法:先做好一|几棵树、草的三l模型,然后在画一帧画面时Q不停的在不同的位置、方向,用不同的大小为参敎ͼ调用DirectX API的绘制函数来画这些模型,可以画出很多草木来。但是每M,都要讄一大堆参数后调用一ơAPIQ这是很耗CPU旉的,所以在以前的游戏中鲜有大规模且l节丰富的森林场景?/p>
而在DirectX 10中,我们可以先把树、草的几个模型设l显卡,然后所有要ȝ树木的位|、方向和大小一ơ性的写入到constant buffer中,q样Q显卡便一下把所有的树木和草都一L制出来了?/p>
MQDirectX 10通过提前数据验证、纹理阵列、绘刉、流式输出、状态对象、常量缓冲等机制Q帮助游戏的效果和效率上升到一个新的高度。这P也避免了之前DirectX版本因CPU负蝲q大而无法对囑Ş实施更多l节优化的问题?/p>
DirectX 10另一个引人瞩目的Ҏ便是引入了Shader Model 4.0Q那么,Shader Model 4.0能够带来怎样的新Ҏ,特别是将它与DirectX 9.0c中Shader Model 3.0相比Ӟ 引入新Shader : Geometry shader DirectX 10新引入的Geometry ShaderQ可以简单地~程操纵几何囑օQ同Ӟ vertex、geometry、pixel shader采用了统一的Sahder架构?/p>
Geometry shaders是可~程囑Ş水U的一大进步。它W一ơ允许由GPU来动态的生成和销毁几何图元数据。通过和新的数据流输出功能配合使用Q许多以前无法实施的法现在都可以在GPU中用了?/p>
l一的Shader架构 在DirectX 9中,Pixel shaderL在各个方面落后于vertex shadersQ包括常量寄存器个数、可用的指o个数、shader长度{。程序员需要区分对待这两种shader?/p>
而在shader model 4中,无论 vertex、geometry和pixel shaderQ均有统一的指令集、同L临时/帔R寄存器个敎ͼ它们^{的׃nGPU中的所有可用资源。这P在编E时便不必再考虑每种shader自n的限制了?/p>
癑ր于DirectX 9的可用资?/em> 对于shader中可用的资源Q在Shader model 4.0中比原来有了惊h的扩充。就像早期的E序员们l尽脑汁的省着用可怜的640k内存一P在用以前的DirectX开发游戏的q程中,E序员需要小心翼的分配珍贵的shader寄存器资源。寄存器的数量,直接影响着shaderE序的复杂度。这和在640k内存?机器上,怎么也不可能写出Microsoft Officeq样的大规模软g是同一个道理?/p>
而在DirectX 10中,时寄存器由原来的32个扩充到?096个,常量寄存器由原来的256个扩充到?5536个?/p>
更多的渲染目?Render Target) 所谓渲染目标,是指GPU可以把画面绘制到的目标,我们可以把它理解为GPU的画布。一般来_渲染目标被输出到屏幕上,q样我们p看到d的画面了。但是有时ؓ了实C些特效,某些渲染l果q不直接d屏幕上,而是再返lGPU做进一步的Ҏ处理Q而且渲染目标中也不一定是d的画面的颜色信息?/p>
Ҏ囑ŞҎ的需要,渲染目标可能是每个物体距dq的q近Q或者物体表面上每个像素的方向,或者每个物体表面的温度{等Q之Z实现ҎQ可以按需要在其中l制M信息。ؓ了提高这U情况下的效率,很多新的昑֍都支持在同一遍Shader执行l束后,同时把不同的信息l制C同的渲染目标中。在DirectX 9中就已经支持q种机制了,但是它约束最多同时向四个渲染目标l制。而DirectX 10这个数量提升了一倍?/p>
更多的纹?/em>
在Shader Model 4.0中提供了对纹理阵?Texture arrays)的支持。在前文中已l对U理阵列有了比较详细的介l,在这里只着重介l一下与shader相关的部分?/p>
在每个纹理阵列中Q最多可以保?512张同样大的U理。而且每张贴图的分辨率被扩展到?192×8192。更大的分L率意味着U理中更丰富的细节。在一个shader中能够同时访问的U理个数被增加到?28个,也就是说在每ơ执行同一个shaderӞ可以使用一个纹理阵列的512个纹理中?28个。所以说Q在DirectX 10中,U理的多h和l节E度会有大q的提升?/p>
新的HDR颜色格式 要说q些q来在实时图形界炒得最热的概念Q应该是HDR了。它通过采用点格式的颜色格式来为纹理、光照等计算提供极大的精度和颜色范围(以前的纹理一?都是采用整数型的颜色格式)。尽最后显C到屏幕上还是每个颜色通道8位的整数格式Q但是以前由于在材质、光照计中U理也是用每通道8位的格式来参与计,所以在昄到画面之前,很多l节在低精度的q算中丢׃?/p>
而采用每颜色通道16位QҎ的纹理,能够保证在运过E中几乎没有颜色l节信息的丢失。另外,采用16位QҎ式的颜色通道Q可以表现更大的颜色范围。这些就是HDR的优性?/p>
对用戯言Q当游戏中的画面|上一层HDR效果后,立刻昑־和真正的照片一P有朦胧的光晕、细致的高光和十分自然的色调?/p>
然而,采用每个颜色通道16位QҎ的格式,比采用每通道8位的整数格式的纹理要多占据一倍的昑֭Q这l绘制的效率带来了负面的影响。所以在 DirectX 10中引入了两个新的HDR格式。第一U是R11G11B10Q表C红色和l色通道?1位QҎQ而蓝色通道采用10位QҎ表示。那么,Z么不都用 11位呢Q这是ؓ了凑32q个整数。学q计机的h都知道,当内存中一个数据单元的宽度?2位时Q对它的操作效率最高;而且在纹理数据中一般要求每个像素的数据宽度?的倍数Q如2,8,16,32,64{等。又因ؓ人眼对蓝色的敏感度不如对U色和绿Ԍ所以它比其他两个通道用了一位?/p>
另外一U格式是采用每通道9位尾数、所有通道׃n5位指数的形式(众所周知Q在计算ZQQҎ是采用尾数附加指数的形式来表C的)Q加hq是32位?q些新的格式使得U理能够与原来占用同样多的显存空_避免了大的空间和带宽消耗。同ӞZ适合需要精的U学计算的场合,DirectX 10能够支持每通道32?4个通道加v?28?_ֺ的QҎU理?/p>
DirectX 10中带来的q些扩充和提高,使得创徏前所未有的细节的实时游戏场景真正成ؓ可能?/p>
在DirectX 10发布之前Q图形硬件只有在GPU上操作已有数据的能力。顶点着色器(Vertex Shader)和像素着色器(Pixel Shader)都允许程序操作内存中已有的数据。这U开发模型非常成功,因ؓ它在复杂|格蒙皮和对已有像素q行_计算斚w都表现的很出艌Ӏ但是,q种开发模型不允许在图像处理器上生成新数据。当一些物体在游戏中被动态的创徏?比如新型武器的外?Q就需要调用CPU。可惜现在大多数游戏已经很给CPU带来了很大的压力Q游戏进行时动态创建庞大数量新数据的机会就变得微乎其微了?/p>
Shader Model 4.0中引入的几何着色器(Geometry Shader)Q第一ơ允许程序在囑փ处理器中创徏新数据。这一革命性的事g使得GPU在系l中的角色由只可处理已有数据的处理器变成了可以以极快速度既可处理又可生成数据的处理器。在以前囑Şpȝ上无法实现的复杂法现如今变成了现实?/p>
几何着色器被放在顶点着色器和光栅化阶段(Rasterizer)中间。所谓光栅化Q就是一行一行的扫描每个三角形,把它们一个像素一个像素的l制到画?上。几何着色器把经q顶点着色器处理q的点当作输入Q对于每个顶点,几何着色器可以生成1024个顶点作出。这U生成大量数据的能力叫做数据扩大 (Data Amplification)。同LQ几何着色器也可以通过输出更少的顶Ҏ删除点Q因此,叫做数据羃?Data Minimization)。这两个新特性GPU在改变数据流斚w变得异常强大?/p>
l分的虚拟位U脓?Displacement Mapping with Tessellation) 几何着色器让虚拟位U脓囑֏以在GPU上生成。虚拟位U脓图是在离U渲染系l中非常行的一Ҏ术,它可以用一个简单的模型和高度图(Height Map)渲染出非常复杂的模型。高度图是一张用来表C模型上各点高度的灰度图。渲染时Q低多边形的模型会被l分成多边Ş更多的模型,再根据高度图上的信息Q把多边形挤出,来表现细节更丰富的模型?/p>
而在DirectX 9中,GPU无法生成新的数据Q低多边形的模型无法被细分,所以只有小部分功能的虚拟位U脓囑֏以实现出来。现在,使用DirectX 10的强大力量,C千计的顶点可以凭I创造出来,也就实现了实时渲染中真正的细分的虚拟位移贴图?/p>
Z边缘(Adjacency)的新法 几何着色器可以处理三种囑օQ顶炏V线和三角Ş。同LQ它也可以输三种囑օ中的M一U,虽然每个着色器只能输出一U。在处理U和三角形时Q几何着 色器有取得边~信息的能力。用线和三角Ş边缘上的点Q可以实现很多强大的法。比如,边缘信息可以用来计算卡通渲染和真实毛发渲染的模型轮廓?/p>
式输出(Stream Output) 在DirectX 10之前Q几何体必须在写入内存之前被光栅化ƈ送入像素着色器(pixel shader)。DirectX 10引入了一个叫做数据流式输?Stream Output)的新Ҏ,它允许数据从点着色器或几何着色器中直接被传入帧缓冲内?Frame Buffer Memory)。这U输出可以被传回渲染水UK新处理。当几何着色器与数据流输出l合使用ӞGPU不仅可以处理新的囑Ş法Q还可以提高一般运和物理q算的效率?/p>
在生成、删除数据和数据输些技术的支持下,一个完整的_子pȝ可以独立地在GPU上运行了。粒子在几何着色器中生成,在数据扩大的q程中被扩大与派生。新的粒子被数据输出到内存Q再被传回到点着色器制作动画。过了一D|_它们开始逐渐消失Q最后在几何着色器中被销毁?br> DirectX 10 Z前的DirectX 9中的“高着色语a”(High Level Shading Language )带来了诸多功能强大的新元素。其中包括可以提升常量更新速度?#8220;帔R~冲?#8221;(Constant Buffers)Q提升渲染流E中操作数据的灵zL的“视图”(view)Qؓ更广泛的法所准备?#8220;整数与位指o”(Integer and Bitwise Instructions)Q添加了switch语句?/p>
帔R寄存?Constant Buffers) 着色程序同普通的E序一样需要用常量来定义各种参数Q例如光源的位置和颜Ԍ摄像机的位置和投q阵以及一些材质的参数(例如反光?。在整个渲染的过E中Q这些常量往往需要频J的更新Q而数以百计的帔R的用以及更新无疑会lCPU带来极大的负载。DirectX 10中新加入的常量缓冲器可以Ҏ他们的用频率将q些帔R分配到指定的~冲器中q协调的对其q行更新?/p>
在一个着色程序中DirectX 10支持最?6个常量缓冲器Q每一个缓冲器可以存放4096个常量。与其相比DirectX 9实在是少得可怜,因ؓ它在每个着色程序中同时最多只能支?56个常量?/p>
相比DirectX 9QDirectX 10不仅提供了更多的帔RQ最主要的是它大q的提升了常量更新的速度。对那些被分配到同一个缓冲器中的帔RQ我们只需q行一ơ操作就可以它们全部更新完毕,而非单个单个的去更新?/p>
׃不同的常量更新的旉间隔各异Q所以跟据用的频率来对他们q行l织可以获得更高的效率。D例来_摄像机的视矩阵只在每一帧之间发生改变,而类D图信息这L材质参数却会在图元切换时发生改变。于是这些常量缓冲器被分成了两个部分Q那些每帧更新的帔R~冲器专门存N些需要在两间更新的常数q在两间一ơ把他们全部更新Q另外的囑օ切换更新的常量缓冲器也同理。这样就会将更新帔Rq程中的一些不必要的工作消除,以便让整个着色器脚本比在 DirectX 9中运行的更加畅?/p>
视图(Views)
在DirectX 9中,着色器(shader)中的数据的类型是被严格划分开的。例如,点着色器用到的顶点缓冲器中的数据不能当作贴图的数据来让像素着色器使用。这样就特定的资源cd同其相对应的渲染程中的特定步骤紧密地结合了hQ同旉制了资源资源在整个渲染流E中可以使用的范围?/p>
DirectX 10舍弃?#8220;严格区分的数据类?#8221;q一概念。当一D|据被创徏Q那么DirectX 10所做的仅仅是将其简单的当作内存中的一D区?bit field)来对待。如果要想用这一D|有定义类型的数据必通过使用一?#8220;view”?使用“view”Q相同的一D|据就可以有各U各LҎ来读取。DirectX 10支持对同一D资源在同时使用两个“view”?/p>
通过q种多重“view”的手D,可以在整个渲染程的不同部分以不同目的使用同一D|据。例如:我们可以通过像素着色器一D几何数据渲染到一张纹?上,之后点着色器通过一?#8220;view”这张纹理视Z个顶点缓冲器q将其中的数据作为几何数据渲染?#8220;view”通过在整个渲染流E中的不同步骤重?使用同一D|据ؓ“数据处理”带来了更大的灉|性,帮助开发者实现更多更有创意更_ֽ的特效?/p>
整数与位q算指o(Integer and Bitwise Instructions) 在新的高U着色器语言中添加了“整数与位指o”Q这h“整数与位q算指o”的操作加入其基础q算函数的好处在于帮助一些算法在GPU上的实现。开发者终于可以直接用整数而非从Q点中{来计出准确的答案。数l的索引L在可以轻杄计算出来。GPU无整数运的时代l于被终l了。这ؓshader E序的开发带来很大的便利?/p>
Switch 语句(Switch Statement) 在DirectX 10中, HLSL可以支持switch语句Q这大q简化那些有着大量判断(分支)的着色器脚本的编码。一U用法就是徏立一?#8220;航母U的着色器(shader) E序”——包含了大量的小型着色器E序q且自n体Ş巨大的着色器E序。在q个“航母U的着色器E序”Q我们可以通过讑֮一个材质ID在switch语句?判断来轻杄在渲染同一个图元时切换不同的特效。也是_现在一个军队中的每个士兵n上都可以拥有各自不同的特效了?/p>
alpha to coverage 在游戏中Q经怋用带有半透明信息U理的多边Ş模型来模拟复杂的物体Q例如,草、树叶、铁丝网{。如果用真正的模型Q一颗边~参差不齐的草可能p消耗掉几百个多边ŞQ然而采用透明U理Q可以只??个多边Şp决了?/p>
然而,当用这U有半透明信息的纹理时候,它的不透明和透明部分的边界线上,常常会出现难看的锯。采用半透明混合技术可以解册个问题,但是它需要把场景中所有这cȝ体按照由q到q的序来绘Ӟ才能保证它们的遮挡关pL正确的,q会lCPU带来很大的压力,q不可取。在以前版本的DirectX中,alpha试和合简直就是图形程序员的噩梦?/p>
在DirectX 10中,使用了一U新的技术叫做Alpha to coverage。用这U技术,在透明和不透明交界处的U理像素会被q行多极取样(Multi-sample)Q达到抗锯的效果。这在不引入大的性能开销的情况下单ƈ有效地解决了q个问题。室外场景的游戏大大受益于q种技术,树叶、铁丝网、草的边~将会更加柔和、圆滑?/p>
shadow map filtering 阴媄?Shadow map)技术已l逐渐成ؓ了渲染真实感阴媄的流行技术。在包括《战争机器》、《分裂细胞:双重特工》、《Ghost Recon》、《刺客信条》等的各大次世代游戏中都能看到它的n影。然而,׃shadow map的尺寔RӞ用它实现的阴p~往往有明昄锯。在DirectX 10中,提供了对shadow mapq行qo的功能的正式支持。经q过滤后Q阴q边缘会变得更加柔和?/p>
const int ival=1024; const 引用可以初始化ؓ不同cd的对象或者初始化为右?/span>Q如字面值常量: double dval=3.14; 非const引用只能l定C该引用同cd的对象?br>const引用则可以绑定到不同但相关的cd的对象或l定到右倹{?/span> 在C++中真正的临时对象是看不见的,它们不出现在你的源代码中。徏立一个没有命名的非堆Qnon-heapQ对象会产生临时对象。这U未命名的对象通常在两U条件下产生Q?span style="COLOR: #ff00ff">Z使函数成功调用而进行隐式类型{换和函数q回对象时?/span>理解如何和ؓ什么徏立这些时对象是很重要的Q因为构造和释放它们的开销对于E序的性能来说有着不可忽视的媄响?br>首先考虑Z函数成功调用而徏立时对象这U情c当传送给函数的对象类型与参数cd不匹配时会生这U情c?/p>
在字W计数的例子里,能够成功传递char数组到countChar中,但是在这里试囄char数组调用upeercasify函数Q则不会成功Q。考虑一下这个函敎ͼ 不能使用void*指针保存const 对象的地址Q而必ȝconst void*cd的指针保存?/span> 允许把非const 对象的地址赋给指向const 对象的指?/span>Q?br>double dval=3.14;Shader Model 4.0
几何着色器与流式输?/h2>
高渲染语言(HLSL 10)
DirectX 10的其他改q?/h2>
透明U理C意
Alpha to coverage效果
const int &refVal=ival; //ok,both reference and object are const
int &ref2=ival; //error! non const reference to a const object
可以d但不能修改refVal,因此QQ何对refVal的赋值都是不合法的。这个限制有其意义:不能直接对ival同|因此不能通过使用refVal来修改ival?br>同理Q用ival初始化ref2也是不合法的Qref2是普通的非const引用Q因此可以用来修改ref2 指向的对象的倹{能qref2对ival赋gD修改const对象的倹{ؓLq样的修改,需?span style="COLOR: #ff00ff">规定普通的引用l定到const对象是不合法的?/span>
int i=42;
// legal for const reference ONLY!
const int &r=42;
const int &r2=r+i;
const int &r3=dval;
~译器展开Q?br>int temp=dval;
const int &ri=temp;
void uppercasify(string& str);
char subtleBookPlug[] = "Effective C++";
uppercasify(subtleBookPlug); // 错误!
没有Z调用成功而徏立时对象,Z么呢Q?br>假设建立一个时对象,那么临时对象被传递到upeercasify中,其会修改q个临时对象Q把它的字符Ҏ大写。但是对subtleBookPlug函数调用的真正参数没有Q何媄响;仅仅改变了时从subtleBookPlug生成的string对象。无疑这不是E序员所希望的。程序员传递subtleBookPlug参数到uppercasify函数中,期望修改subtleBookPlug的倹{当E序员期望修攚w临时对象Ӟ寚w帔R引用Qreferences-to-non-constQ进行的隐式cd转换却修改时对象?span style="COLOR: #ff00ff">q就是ؓ什么C++语言止为非帔R引用Qreference-to-non-constQ生时对象?/span>q样非常量引用(reference-to-non-constQ参数就不会遇到q种问题?br>
把一个const对象的地址赋给一个普通的Q非const对象的指针也会导致编译时错误Q?br>const double pi=3.14;
double *ptr=π //error:ptr is a plain pointer
const double *cptr=π //ok:cptr is a pointer to const
const int universe=42;
const void *cpv=&universe; //ok;
void *pv=&universe; //error:universe is const
cptr=&dval;
const pstring cstr;
//cstr is a const pointer to string
string *const cstr ; // equivalent to const pstring cstr;
Sales_item成员函数形参表后面的const后面所L作用:const 改变了隐含的this 形参的类?/span>。在调用
total.same_isbn(trans)Ӟ隐含的this形参是一个指向total对象的const Sales_item *cd的指针?br>׃this 是指向const对象的指针,const 成员函数不能修改调用该函数的对象?br>const 对象Q指向const对象的指针或引用只能用于调用其const成员函数Q如果尝试用它们调用?br>const 成员函数Q则是错误的?
]]>
]]>
回调函数是基于C~程的Windows SDK的技术,不是针对C++的,E序员可以将一个C函数直接作ؓ回调函数Q但是如果试囄接用C++的成员函C为回调函数将发生错误Q甚至编译就不能通过?br />分析原因Q?/font>
普通的C++成员函数都隐含了一个传递函C为参敎ͼ亦即“this”指针,C++通过传递一个指向自w的指针l其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解ؓ什么C++cȝ多个实例可以׃n成员函数但是有不同的数据成员。由于this指针的作用,使得一个CALLBACK型的成员函数作ؓ回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失?br />解决ҎQ?/font>
一,不用成员函敎ͼ直接使用普通C函数Qؓ了实现在C函数中可以访问类的成员变量,可以使用友元操作W?friend)Q在C++中将该C函数说明?font color="#ff1493">cȝ友元卛_。这U处理机制与普通的C~程中用回调函C栗?br />?使用静态成员函?/font>Q静态成员函C使用this指针作ؓ隐含参数Q这样就可以作ؓ回调函数了。静态成员函数具有两大特点:其一Q可以在没有cd例的情况下用;其二Q只能访问静态成员变量和静态成员函敎ͼ不能讉K非静态成员变量和非静态成员函数。由于在C++中用类成员函数作ؓ回调函数的目的就是ؓ了访问所有的成员变量和成员函敎ͼ如果作不到这一点将不具有实际意义。我们通过使用静态成员函数对非静态成员函?font color="#ff1493">包装的办法来解决问题。类实例可以通过附加参数?font color="#ff1493">全局变量的方式的方式传递到静态成员函C。分别D例如下:
1Q参C递的方式
#include <iostream.h>
class TClassA
{
public:
void Display(const char* text) { cout << text << endl; };
static void Wrapper_To_Call_Display(void* pt2Object, char* text);
// more....
};
// 静态包装函敎ͼ能够调用成员函数Display(),本n做ؓ回调函数来?/font>
void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string)
{
// 昑ּcd转换
TClassA* mySelf = (TClassA*) pt2Object;
// 调用普通成员函?br /> mySelf->Display(string);
}
// 回调函数的宿?在这里回调用函数被?br /> void DoItA(void* pt2Object, void (*pt2Function)(void* pt2Object, char* text))
{
// 使用回调函数
pt2Function(pt2Object, "hi, i'm calling back using a argument ;-)");
}
// 执行CZ
void Callback_Using_Argument()
{
TClassA objA;
DoItA((void*) &objA, TClassA::Wrapper_To_Call_Display);
}
2Q全局变量的方?br /> #include <iostream.h>
void* pt2Object; // 全局变量,可以指向L对象
class TClassB
{
public:
void Display(const char* text) { cout << text << endl; };
static void Wrapper_To_Call_Display(char* text);
};
// 静态的包装函数
void TClassB::Wrapper_To_Call_Display(char* string)
{
//需要保证全局变量值的正确?br /> TClassB* mySelf = (TClassB*) pt2Object;
mySelf->Display(string);
}
// 回调用函数的宿主,在这里回调用函数被?br /> void DoItB(void (*pt2Function)(char* text))
{
pt2Function("hi, i'm calling back using a global ;-)"); // make callback
}
// 执行CZ
void Callback_Using_Global()
{
TClassB objB;
pt2Object = (void*) &objB;
DoItB(TClassB::Wrapper_To_Call_Display);
}
注意Q通过上面两种Ҏ的比较可以看出,W?U方法中静态包装函数可以和普通成员函C持签名一_当回调函数的宿主接口不能改变Ӟq种Ҏ特别有用。但因ؓ使用了全局变量Q也不是一个好的设计?/p>
可能有好多hQ包括C语言老手都不知道如何float数据转换为stringQ我是q样Q今天查了一下MSDNQ才知道C提供了_gcvt函数实现q个功能Q收L实不,Z方便自己查询Q也Z那些像我q样的网友能够了解该函数的具体用法,我把MSDN的原文原不动抄录如下:
Converts a floating-point value to a string, which it stores in a buffer.
char *_gcvt( double value , int digits , char * buffer );
Routine | Required Header | Compatibility |
_gcvt | <stdlib.h> | Win 95, Win NT |
For additional compatibility information, see Compatibility in the Introduction.
Libraries
LIBC.LIB | Single thread static library, retail version |
LIBCMT.LIB | Multithread static library, retail version |
MSVCRT.LIB | Import library for MSVCRT.DLL, retail version |
Return Value
_gcvt returns a pointer to the string of digits. There is no error return.
Parameters
value
Value to be converted
digits
Number of significant digits stored
buffer
Storage location for result
Remarks
The _gcvt function converts a floating-point value to a character string (which includes a decimal point and a possible sign byte) and stores the string in buffer. The buffer should be large enough to accommodate the converted value plus a terminating null character, which is appended automatically. If a buffer size of digits + 1 is used, the function overwrites the end of the buffer. This is because the converted string includes a decimal point and can contain sign and exponent information. There is no provision for overflow. _gcvt attempts to produce digits digits in decimal format. If it cannot, it produces digits digits in exponential format. Trailing zeros may be suppressed in the conversion.
Example
/* _GCVT.C: This program converts -3.1415e5 * to its string representation. */#include <stdlib.h>#include <stdio.h>void main( void ){ char buffer[50]; double source = -3.1415e5; _gcvt( source, 7, buffer ); printf( "source: %f buffer: '%s'\n", source, buffer ); _gcvt( source, 7, buffer ); printf( "source: %e buffer: '%s'\n", source, buffer );}
Output
source: -314150.000000 buffer: '-314150.'source: -3.141500e+005 buffer: '-314150.'
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=708935
在一些大的工E中Q可能会包含几十个基c,免不了之间会互相引用 ( 不满承关p,而是l合关系 ) 。也是需要互相声明。好了,q时候会带来一些乱。如果处理得不好Q会搞得一团糟Q根据我的经验,单谈谈自已的处理办法Q?/font>
~码Ӟ我们一般会量避免
include
头文Ӟ而是采用声明
class XXX
?/font>
但有时候还是必ȝ
Include
头文Ӟ那么Q两者的划分在于什么呢Q?/font>
应该是很明确的,但书上好像都有提及?/font>
首先Q?/font>
我们要明白ؓ什么要用声明取代头文g包含Q对了,是ؓ了避免无必要的重~译
(
在头文g发生变更?/font>
)
?/font>
工程较大Q低速机Q或基础cȝ常变?/font>
(
不合理的设计?/font>
)
Q编译速度q是会在意的Q?/font>
另外Q更为重要的是,采用声明可降低代?/font>
(class)
之间的藕合度Q这也是面向对象设计的一大原则?/font>
二:一般原则:
a.
头文件中量?/font>
include,
如果可以单申?
class clsOld;
解决Q那最好。减没有必要的
includeQ?br />b.
实现文g中也要尽量少
include,
不要
include
没有用到的头文g?
三:那什么时候可以只是简单声?/font>
class clsOld
呢?
单的_不需要知?/font>
clsOld
的内存布局的用法都可以
(
静态成员除?/font>
)
Q也是讲如果是指针或引用方式的
都行?/font>
比如Q?/font>
clsOld * m_pOld; //
指针?/font>
4
个字节长
clsOld & test(clsOld * pOld) {return *pOld};
一?/font>
OK
?/font>
四:什么时候不能简单声?/font>
class clsOld
Q必?/font>
include
呢?
不满三的情况下Q?/font>
比如Q?/font>
clsOld m_Objold; //
不知道占据大,必须要通过它的具体声明来计?/font>
原因很简单,x你要计算
sizeof(classNew)
Q但q?/font>
clsOld
?/font>
size
都不知道Q编译器昄会无能ؓ力?/font>
Ҏ情况Q?/font>
int test() { return clsOld::m_sInt;}
静态成员调用,x应该是不需要知道内存布局的,但因为需要知?/font>
m_sInt
是属?/font>
clsOld
命名I间
的,如果只声?/font>
class xxx
昄是不以说明的,所以必d含头文g?/font>
lg所qͼ我有以下几点Q?/font>
1
Q如果有共同相关依赖
(
必须
include)
的类Q比?
A,B
都依?/font>
D
可以攑֜一P然后直接
Include "d"
cȝ使用者只需兛_与本cL露出的相关类型,内部用到的类型不用去?/font>
(
不用自已?/font>
include d)
。这?/font>
l出?/font>
class
Q调用者才更好?/font>
(
不用ȝ代码查找Q是不是q需要包含其它头文g
)
?/font>
2 Q如?/font> A cM?/font> D B cM依赖 D Q可以把它们分开两个头文件。各?/font> Include 。这样可避免?/font> D 发生变化Ӟ 避免不必要重~译?/font>
3
Q类中尽量采用指针或引用方式调用其它c,q样可以只声明
class xxx
了。ƈ且这也符合资源最?/font>
利用Q更利于使用多态?br />
/--------------------------------------------------/////////////////////////////////////////////////////////////////////////////
今天?span lang="EN-US">VC++~译我这昨天写的代码时发现L通不q,看到大部分的错误都是与一个类的定义有兟?span lang="EN-US">
明明我已l在q个cM定义了一个成员变量,可编译器偏要说那个变量不是这个类的成员。没办法Q找了半天原因还是没有头l。再三地认不是?span lang="EN-US">C++的语法错误之后。我开始怀疑是不是头文件的问题。因为当我把一?strong>#include "..."搬到#pragma once之前或者之后,错误报告׃发生变化。有时就只是说我的一个类重复定义了?span lang="EN-US">
以前?span lang="EN-US">C写头文g的时候都是用宏定义来避免重复包含头文?/strong>?span lang="EN-US">C++里虽然也q可用这个方法,?span lang="EN-US">VC++是不用Q它用的?strong>#pragma once。这一变化Ҏ来说真是有点怸着头脑了,我不清楚#pragma once的工作方式是如何的。而我现在遇到的问题又与这个有兟뀂找扄上的内容看吧。上google搜了半天Q那些论坛里的回{基本上都是“防止重复包?strong>头文?/strong>的,你不用管他。”这L。可是不他真的行吗Q我刚学?span lang="EN-US">VC++Q我看的书上是没有讲q这个内容的。怎么在网上也搜不到呢Q经q我不懈的努力,l于让我扑ֈ了一?span lang="EN-US">http://www.yesky.com/127/1736627_3.shtml?span lang="EN-US">
作?span lang="EN-US">Adding的这D话Ҏ的帮助最大:?/span>
既然使用了包含文ӞZ么还要在class CMainFrame前添?span lang="EN-US">"class CViewerView;"{代码?如果用包含文件代替它Q行不行Q 很多Visual C++书籍对这些问题避而不谈,但实际上q是一个重要的问题。如果不能理解上qC码,我们很可能ؓ无法通过~译而大伤脑{。这些问题的出现是基于这L一些事实:在我们用标准C/C++设计E序Ӟ有一个原则即两个代码文g不能怺包含Q而且多次包含q会造成重复定义的错误。ؓ了解册个难题, Visual C++使用#pragma once来通知~译器在生成时只包含(打开)一ơ,也就是说Q在W一?span lang="EN-US">#include之后Q编译器重新生成时不会再对这些包含文件进行包?span lang="EN-US">(打开)和读取,因此我们看到在用向导创徏的所有类的头文g中有#pragma once语句׃会觉得奇怪了。然?span style="COLOR: red">正是׃q个语句而造成了在W二?span lang="EN-US">#include后编译器无法正确识别所引用的类。因此,我们在相互包含时q需要加入类?span lang="EN-US">class CViewerViewq样的语句来通知~译器这个类是一个实际的调用?/span>
?span lang="EN-US">
看来是q个问题了。把我的代码一加上那些cȝ声明以后果然通过了编译。我感觉q个问题?span lang="EN-US">VC++里面来说应该是值得注意的。可能是׃我刚?span lang="EN-US">VC++Q见识太的原故吧。无论如何先C来,说不定也有h在ؓq个#pragma once伤脑{呢?span lang="EN-US">
int i = 100;
long l = 2001;
float f=300.2;
double d=12345.119;
char username[]="E佩?;
char temp[200];
char *buf;
CString str;
_variant_t v1;
_bstr_t v2;
一、其它数据类型{换ؓ字符?/b>
char buffer[200]; char c = '1'; int i = 35; long j = 1000; float f = 1.7320534f; sprintf( buffer, "%c",c); sprintf( buffer, "%d",i); sprintf( buffer, "%d",j); sprintf( buffer, "%f",f);
二、字W串转换为其它数据类?/font>
strcpy(temp,"123");
三、其它数据类型{换到CString
使用CString的成员函数Format来{?例如:
四、BSTR、_bstr_t与CComBSTR
五、VARIANT 、_variant_t ?COleVariant
本主题演C如何将各种 C++ 字符串类型{换ؓ其他字符丌Ӏ可以{换的字符串类型包?char *?strong>wchar_t*?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl03',this);" >_bstr_t?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl04',this);" >CComBSTR?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl05',this);" >CString?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl06',this);" >basic_string ?System.String。在所有情况下Q在字W串转换为新cdӞ都会创徏字符串的副本。对新字W串q行的Q何更攚w不会影响原始字符Ԍ反之亦然?/p>
此示例演C如何从 char * 转换Z面列出的其他字符串类型?/p>
// convert_from_char.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { char *orig = "Hello, World!"; cout << orig << " (char *)" << endl; // Convert to a wchar_t* size_t origsize = strlen(orig) + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string string basicstring(orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)
此示例演C如何从 wchar_t * 转换Z面列出的其他字符串类型?/p>
// convert_from_wchar_t.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { wchar_t *orig = L"Hello, World!"; wcout << orig << L" (wchar_t *)" << endl; // Convert to a char* size_t origsize = wcslen(orig) + 1; const size_t newsize = 100; size_t convertedChars = 0; char nstring[newsize]; wcstombs_s(&convertedChars, nstring, origsize, orig, _TRUNCATE); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (wchar_t *) Hello, World! (char *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)
此示例演C如何从 _bstr_t 转换Z面列出的其他字符串类型?/p>
// convert_from_bstr_t.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { _bstr_t orig("Hello, World!"); wcout << orig << " (_bstr_t)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, (char *)orig); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, (wchar_t *)orig); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a CComBSTR CComBSTR ccombstr((char *)orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring((char *)orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string string basicstring((char *)orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String((char *)orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (_bstr_t) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)
此示例演C如何从 CComBSTR 转换Z面列出的其他字符串类型?/p>
// convert_from_ccombstr.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { CComBSTR orig("Hello, World!"); CW2A printstr(orig); cout << printstr << " (CComBSTR)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; CW2A tmpstr1(orig); strcpy_s(nstring, tmpstr1); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, orig); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (CComBSTR) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)
此示例演C如何从 CString 转换Z面列出的其他字符串类型?/p>
// convert_from_cstring.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { CString orig("Hello, World!"); wcout << orig << " (CString)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, orig); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* // You must first convert to a char * for this to work. size_t origsize = strlen(orig) + 1; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a basic_string string basicstring(orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (CString) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (basic_string) Hello, World! (System::String)
此示例演C如何从 basic_string 转换Z面列出的其他字符串类型?/p>
// convert_from_basic_string.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { string orig("Hello, World!"); cout << orig << " (basic_string)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, orig.c_str()); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* // You must first convert to a char * for this to work. size_t origsize = strlen(orig.c_str()) + 1; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig.c_str()); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig.c_str()); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig.c_str()); cstring += " (CString)"; cout << cstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig.c_str()); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }
Hello, World! (basic_string) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (System::String)
此示例演C如何从 System.String 转换Z面列出的其他字符串类型?/p>
// convert_from_system_string.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { String ^orig = gcnew String("Hello, World!"); Console::WriteLine("{0} (System::String)", orig); pin_ptr<const wchar_t> wch = PtrToStringChars(orig); // Convert to a char* size_t origsize = wcslen(wch) + 1; const size_t newsize = 100; size_t convertedChars = 0; char nstring[newsize]; wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, wch); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(wch); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(wch); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(wch); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(wch); basicstring += L" (basic_string)"; wcout << basicstring << endl; delete orig; }
Hello, World! (System::String) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string)