• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Introduction to C++ over CLI
 

Introduction to C++ over CLI

on

  • 1,801 views

本講題將對C++/CLI做一個概觀性的介紹。...

本講題將對C++/CLI做一個概觀性的介紹。
在C++/CLI之前,.NET平台上的C++開發方案,多半只能選擇採用Managed C++。無可諱言的,Managed C++本身存在一些改善的空間,諸如:語法的優雅與寫作的流暢、對泛型程式設計的支援等等。然而,在著名的C++語言大師Stan Lippman及Herb Shtter加入VC++的團隊中時,重新制定後的C++/CLI卻讓這些問題得到了解決的方案。在Visual Studio 2005中,完全支援C++標準的C++/CLI加入了新語法及語義,針對.NET環境提供了最直接的支援。
有了C++/CLI,原先標準的C++能力不僅不會受損,而C++/CLI中的標準擴充,也使得C++在.NET平台上獲得額外的加持。C++/CLI有了.NET的加持,一舉具備了reflection及垃圾回收的能力。.NET所提供的標準類別庫,也都可為其所用。再加上C++/CLI混合了unmanaged及managed兩種執行環境,更使得C++/CLI具備更多效率的空間,同時能夠開發系統層級的應用程式。
有了C++/CLI,在.NET平台上的C++程式員如同取得一把新的寶劍。

Statistics

Views

Total Views
1,801
Views on SlideShare
1,801
Embed Views
0

Actions

Likes
1
Downloads
29
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introduction to C++ over CLI Introduction to C++ over CLI Presentation Transcript

    • C++/CLI 概觀 王建興 qing@cs.nthu.edu.tw (Email/MSN) 2007/1/25
    • About Qing
      • Education
        • Ph.D. Candidate, Department of Computer Science, National Tsing-Hua University, Taiwan
        • Research interests: distribute network management, mobile agent, VoIP, and p2p networking
      • Software Development Skills
        • Programming languages: 80x86 assembly, C/C++, Java, C#
        • J2EE development and Web programming: EJB, JSP/Servlet
        • Network programming: TCP/IP, socket programming
        • Object Oriented Design/Programming
        • Design Patterns and Software Architecture
        • Distributed Network Management System
        • Peer-to-Peer Networking
      • Book Translation
        • Thinking in Java 2nd Edition, in Traditional Chinese
        • Essential C++, in Traditional Chinese
    • Agenda
      • 何謂 C++/CLI
      • C++/CLI 中的型別宣告
      • Handle vs. Pointer
      • Deterministic Destruction of C++/CLIS
      • C++/CLI 中的陣列
      • C++/CLI 對 Property 的支援
      • C++/CLI 的四種編譯模式
      • Templates 及 Generics
      • C++/CLI 的標準化
    • 在 C++/CLI 出現前, .NET 上的 C++ 程式員恐怕只有一個字可以形容 悶
    • .NET 上的 C++ 程式員為什麼悶? (1/2)
      • 僅管有了 Managed Extension for C++ ,但卻存在一些對程式員的困擾
      • 不夠流暢優雅的語法
        • 例如:雙底線的關鍵字們
      • 對 CLI 的支援不夠支接
        • 例如:缺乏 for-each 語法,不支援 property
      • C++ 與 .NET 之間的整合不夠好
        • 例如:無法在 CLI 型別上使用 template ,也無法在 C++ 型別上運用 CLI 的機制,例如垃圾回收
      *http://www.codeproject.com/managedcpp/cppcliintro01.asp
    • .NET 上的 C++ 程式員為什麼悶? (2/2)
      • 有兩種形式的指標: unmanaged 指標及 managed 指標,其用法及表示容易造成混淆
      • 無法產生 verifiable 的程式碼
    • 為什麼不學 C# 就好了?
      • 多學一個程式語言
      • C++ 最佳化能力較強
      • C++ 具備 deterministic destruction (即使編譯為 MSIL )
      • C++ 程式員在 C++ 的特性支持下,生產力較高
        • STL
        • template specialization
    • 好消息是… .Net 上的 C++ 程式員不用再悶了
    • C++/CLI 所帶來的拯救
      • 優雅流暢的語法
      • 對 CLI 的直接支援
        • property ,泛型,垃圾回收等機制全都有了直接的支援
        • 在 unmanaged classes 上這些機制也都適用
      • 妥善的橋接 .NET 與 C++
      • 透過 C++/CLI 編譯出來的程式碼,是 fully verifiable
      *http://www.codeproject.com/managedcpp/cppcliintro01.asp
    • 何謂 C++/CLI ?
      • C++ 所支援的靜態物件模型,目標放在對執行檔速度及大小的最佳化上
      • CLI 則為一支援動態元件編程模型的多階架構
      • C++/CLI 中的” /” ,代表 C++ 與 CLI 之間的 binding
      • 何謂 C++/CLI
        • 近似說法 1 : C++/CLI 將 C++ 靜態的物件模型繫結 (bind) 至 CLI 的動態元件模型
        • 近似說法 2 : C++/CLI 將 .NET 編程模型整合進到 C++ 中
      * Stanley B. Lippman , http://msdn.microsoft.com/msdnmag/issues/06/00/PureC/default.aspx
    • C++/CLI 就是 C++ X CLI
      • 確定性的記憶體管理
      • Template
      • Native types
      • STL 、 generic algorithms
      • 指標
      • 複製建構及指派
      • 垃圾收集, finalizer
      • 泛型
      • Reference 及 value types
      • Interface
      • Verifiability
      • Security
      • Properties, delegates, events
      • 功能強力的 BCL
      C++ 的特點 CLI 的特點 C++/CLI 發揮 C++ 及 CLI 的相乘效果
    • C++/CLI 的目標就是 無接縫式的整合 Unmanaged 及 Managed Code
    • C++ 及 CLI 物件模型的比較
      • 物件儲存空間類型多樣化
        • static, stack, 以及 heap
      • 物件的生命期類型多樣化
        • static object 有著和程式相同的生命期
        • stack 上的 object ,則在和 scope({ … }) 的生命期相同
        • heap 上的 object ,則由程式員自行操控其生命期
      • 物件建構及指派的深層拷貝模型
      • 編譯時,原始碼中必須含括所有動用型別的資訊
      • 物件儲存空間類型單純
        • Value type 儲存於 stack
        • Reference type 儲存於 managed heap 上
      • 物件的生命期具不確定性
        • Reference types 須倚靠垃圾收集器回收
      • 物件的指派採淺層參考語義
      • 編譯時,型別資訊由所使用型別的 metadata 提供
      C++ 的靜態物件模型 CLI 的動態物件模型
    • C++/CLI 中的型別宣告
      • 在 C++/CLI 中可宣告下述型別
      CLR 的 enumeration type enum class E {…} CLR 的 interface type interface class I {…} CLR 的 value type value class V {…} CLR 的 reference type ref class R {…} C++ 原生類別(過去 C++ 程式員所用) class N {…} 所宣告的型別 宣告語法
    • C++ 與 CTS 型別的對應 N/A Boolean bool N/A Double long double N/A Double double N/A Single float UInt64 Int64 __int64 UInt32 Int32 long int UInt32 Int32 int, __int32 UInt16 Int16 short int Byte Sbyte char CTS Unsigned Type CTS Signed Type C++ Type
    • 各型別的用途
      • 原生型別
        • 具備 native code 的語義及優點
        • 即使被編譯成 MSIL 亦如此
      • Reference Type
        • 可被垃圾收集器回收,提供簡便的記憶體管理模式
      • Value Type
        • 輕量級的型別(例如像整數之類的型別)
      • Interface Type
        • 宣告 CLR 中的介面型別
      • Enumeration Type
        • 宣告 CLR 中的列舉型別
    • 例:在 C++/CLI 中宣告 Reference Type
      • ref class Qing
      • {
      • public:
      • void sayHello();
      • };
      • void Qing::sayHello()
      • {
      • Console::WriteLine("Hello!");
      • }
      多半宣告在 .h 檔裡 多半宣告在 .pp 檔裡
    • Handle vs. Pointer
      • C++/CLI 中將 native C++ 型別及 CLI 型別區分開來
      • C++/CLI 中同樣具備指向 CLI 型別的 ” 指標”,但採用了不同的符號來表示,同時賦予一個不同的名稱,以資區別
        • 這個名稱就是 Handle (相對於 Pointer )
        • 這個符號就是 ^ (相對於 * )
      • 建構 native C++ 型別及 CLI 型別的關鍵字也已有所區隔
        • new :產生 native C++ 型別
        • gcnew :產生 CLI 型別( gc 意指 garbage collected ,垃圾回收之意)
    • 透過 Handle 建構並運用 CLI 型別
      • Qing ^ qing = gcnew Qing();
      • qing->sayHello();
    • 使用 Pointer 和 Handle 的差異
      • Pointer 用來在 native heap 中配置空間
        • 語法: T* t = new T;
        • 指標指向的位置是穩定的(不受 GC 影響),甚至可以被轉型為 int
        • 倘若未自行釋放記憶體( delete ),則會產生 memory leak
      • Handle 用來在 managed heap 中配置空間
        • 語法: T^ t = gcnew T;
        • GC 會自動釋放位於 managed heap 中的物件所佔用的空間
        • 但程式員仍可針對 managed heap 上的物件呼叫 delete
    • 不同的兩種物件生成及運用模式 *Kate Gregory, “Moving C++ Applications to the Common Language Runtime”   Use Native Heap    Use Managed Heap   Use Stack ^ and % always * and & never Verifiability d elete delete Free gcnew new Allocate % & Reference ^ * Pointer / Handle Managed Native
    • 於 Native/CLI 型別中混用 Pointer/Handle (1/2)
      • 在 CLI 型別中使用 Handle
      • 在 CLI 型別中使用 Pointer
      ref class R { private: String ^str; } ref class R { private: std::string* str; }
    • 於 Native/CLI 型別中混用 Pointer/Handle (2/2)
      • 在 Native 型別中使用 Handle
      • gcroot<T> 是用來包裝 System.Runtime.InteropServices.GCHandle 的一個 template class
      *http://www.codeproject.com/managedcpp/ijw_unmanaged.asp class N { private: gcroot<String^> str;; }
    • Tracking Reference Operator %
      • & 之於 pointer ,相當於 % 之於 handle
      R1 ^pr1 = gcnew R1(); R1 %r1 = * pr1; Console::WriteLine(r1 . ToString()); 不再是 -> 同樣使用 *
    • Tracking Reference 的效應 array<String^>^ arr = gcnew array<String^>(3); int i = 0; for each(String^% s in arr) s = gcnew String(i++.ToString()); for each(String^ s in arr) Console::WriteLine(s); 執行結果: 0 1 2 array<String^>^ arr = gcnew array<String^>(3); int i = 0; for each(String^ s in arr) s = gcnew String(i++.ToString()); for each(String^ s in arr) Console::WriteLine(s); 執行結果:
    • CLI 的 Non-Deterministic Finalization
      • CLI 的垃圾回收機制,會在記憶體傾向不足時,將不再使用被物件佔用的記憶體空間回收再用
      • 當物件佔用的記憶體空間確定被回收前的一刻,該物件的 Finalize() 會被呼叫,此即為 finalization (終始化)動作
      • Finalization 執行的時機及是否會被執行任誰都說不得準
        • 所以被稱為 non-deterministic finalization
    • Disposal
      • 對於記憶體資源而言, non-deterministic finalization 不成問題
      • 但對非記憶體資料(例如資料庫 、 檔案), 面對 non-deterministic finalization 的程式員得多費心才能使程式如預期的運作
      • 對 .NET 而言,慣例上清理此類資料的動作,會定義於名為 Close() 或 Dispose() 的方法中
      • 但這麼一來,程式員得自行呼叫 Close() 或 Dispose() 來進行清理動作
    • Deterministic Destruction
      • C++/CLI 除了 CLI 上原先就有的 finalizer 之外,還提供了 destructor.
      ref class R1 { public: R1() {} ~R1() {} protected: !R1() {} }; constructor destructor finalizer * 注意: C++/CLI 使用了 C# 中用來表示 Finalizer 的符號來表示 Destructor
    • Finalizer vs. Destructor
      • C++/CLI 中的 Destructor 最終會被編譯成為 Dispose() ,如果用 C# 的相對應程式碼來看的話,會像是:
      • GC::SuppressFinalize() 會要求系統不要呼叫物件的 finalizer() ,避免物件被清理兩次
      public void Dispose()//IDisposable::Dispose { GC.SuppressFinalize(this); } *http://www.codeproject.com/managedcpp/cppclidtors.asp *http://msdn2.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
    • Why SuppressFinalize? public class FileStream : Stream { public override void Close() { // Clean up this object: flush data and close file … // There is no reason to Finalize this object now GC.SuppressFinalize(this); } protected override void Finalize() { Close(); // Clean up this object: flush data and close file } // Rest of FileStream methods go here … } *http://www.codeproject.com/managedcpp/cppclidtors.asp 如果程式員自行呼叫了 Close() , 但 GC 又呼叫了 Finalize() 便會引發 Close() 被叫用兩次
    • 自動進行的 Disposal { SqlConnection conn(connString); } constructor 會被呼叫 destructor 會被自動呼叫 { SqlConnection ^pConn = gcnew SqlConnection(connString); } constructor 會被呼叫 之後就要等待 GC 動作了
    • C++/CLI 中的陣列
      • 使用 Managed Heap 的 Managed Array ,其基礎型別皆為
      • System::Array
      • 使用 C++/CLI 的陣列時,可以想像存在一個虛擬的 template
      http://www.codeproject.com/managedcpp/cppcliarrays.asp namespace stdcli::language { template<typename T, int rank = 1> ref class array : System::Array {}; }
    • 陣列定義語法
      • 一維陣列語法
      • 多維度陣列語法
      array<String ^> ^ strArray = gcnew array<String ^>(10); for(int i=0;i<strArray->Length;i++) { strArray[i] = &quot;&quot;+i; Console::WriteLine(strArray[i]); } array<String ^, 3> ^ strArray = gcnew array<String ^, 3>(4, 3, 2); 維度 每個維度的長度
    • 陣列的初始化 array<String^>^ strarr = gcnew array<String^> {“String1&quot;, “String2&quot;}; array<String^>^ strarr2 = {“String1&quot;, “String2&quot;}; array<Object^,2> ^ objarr = {{“String1&quot;, 1}, {“String2&quot;, 2}};
    • 參數陣列
      • C++/CLI 支援參數陣列,參數陣列必須是最後一個參數
        • 用…來標示參數陣列
      void testParamArray(String ^s, ... array<String ^>^ params) { Console::WriteLine(s+&quot;: &quot;); for(int i=0;i<params->Length;i++) Console::WriteLine(params[i]); } int main(array<System::String ^> ^args) { testParamArray(&quot;Hello&quot;, &quot;qing&quot;); testParamArray(&quot;Hello&quot;, &quot;qing&quot;, &quot;chrisma&quot;); }
    • Property 的語法 ref class UserAccount { public: property String^ ID { String^ get(){return id;} virtual void set(String^ value){id = value;} } private: String^ id; }; 就和 C# 的定義方式類似
    • Index Property 的語法 ref class OnlineUserList{ public: property UserAccount^ User[int] { UserAccount^ get(int idx){return (UserAccount^) alUser[idx];} } OnlineUserList() { alUser = gcnew System::Collections::ArrayList(); } // … private: System::Collections::ArrayList ^alUser; };
    • Refernece Type 允許單一繼承多重實作 ref class R abstract {}; public ref class R2 : R, IClone, IComparable, IDisposable, IEnumerable { }; 所有 reference type 都繼承自 System::Object 最多繼承一個類別,但可以實作多個介面
    • Exception Handling try { throw gcnew Exception(&quot;qing&quot;); } catch(System::Exception^ e) { Console::WriteLine(e->StackTrace); }
    • CLR 編譯模式:共有四種可供選擇
      • Mix( /clr)
        • 包含 managed/unmanaged code
      • Pure( /clr:pure )
        • 僅包含 managed code
        • 但仍可使用 #include 並呼叫原生 API
      • Verifiable( clr:safe)
        • 僅包含 verifiable code
      • Managed Extensions for C++( clr:oldSyntax )
        • 用來編譯舊式的程式碼
    • 在 VS 2005 中選擇編譯模式
    • 編譯模式之間的關連性 Native CLR Code Data Machine Code CLR Data / Types Native Data / Types MSIL Code Mixed C++ /clr Native C++ Verifiable C++ /clr:safe Pure C++ /clr:pure
    • CLR 編譯模式帶來的應用
      • 在 C++ 應用程式中直接使用 BCL 或以 .NET 寫成的 library
        • 大幅提高生產力
      • 將 native code 的功能,以 .NET 物件模型的方式對外提供
        • 便於其他 .NET 應用程式使用( ASP.NET )
    • 決定 Managed/Unmanaged 的交界處 C++ managed C++ CRT, STL, etc One call to foo() Hundreds of calls C# or C++ managed C++ CRT, STL, etc One call to foo() Hundreds of calls C# C++ CRT, STL, etc Hundreds of calls C++ One call to foo() One call * Kate Gregory, “ Moving C++ Applications to the Common Language Runtime”
    • C++/CLI 支援 Template template<typename T1, typename T2> class NativeData { public: NativeData(T1 t1) { m_t1 = t1; } void DoStuff(T2 t2) { //... } private: T1 m_t1; }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Tempalte 採用 Lazy Constraint (1/2) template<typename T> class Native { public: void Start(int x) { T* t = new T(); t->Bark(x); t->WagTail(); delete t; } }; 如何確定 t 有 Bark() 及 WagTail() 兩 methods 呢? *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Tempalte 採用 Lazy Constraint (2/2) Native<NativeDog> d1; d1.Start(100); Native<NativePig> d2; d2.Start(100); 引發編譯器錯誤: error C2039: 'Bark' : is not a member of 'NativePig' *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • C++/CLI 支援 Generics generic<typename T1, typename T2> ref class GenericData { public: GenericData(T1 t1) { m_t1 = t1; } void DoStuff(T2 t2) { //... } private: T1 m_t1; }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Generics 採用 Subtype Constraints (1/3) generic<typename T> where T:IDog ref class GenRef { public: void Start(int x) { T t = Activator::CreateInstance<T>(); t->Bark(x); t->WagTail(); delete safe_cast<Object^>(t); } }; 透過限制 T 必須實作的介面來進行約束 *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Generics 採用 Subtype Constraints (2/3) ref class ClrDog : IDog { public: virtual void Bark(int Loudness) { Console::WriteLine(&quot;ClrDog::Bark {0}&quot;,Loudness); } virtual void WagTail() { Console::WriteLine(&quot;ClrDog::WagTail&quot;); } }; *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Generics 採用 Subtype Constraints (3/3) GenRef<ClrDog^> g1; g1.Start(100); *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • 使用 Reference Types 於 Template template<typename T> class CLR { public: void Start(int x) { T^ t = gcnew T(); t->Bark(x); t->WagTail(); delete t; } }; CLR<ClrDog> g2; g2.Start(100)
    • 將 Template 宣告為 Reference Type template<typename T> ref class CLR2 { public: void Start(int x) { T^ t = gcnew T(); t->Bark(x); t->WagTail(); delete t; } }; CLR 2 <ClrDog> g 3 ; g 3 .Start(100) Console::WriteLine(g3.GetType()->Name); 執行結果: ClrDog::Bark 100 ClrDog::WagTail CLR2<ClrDog>
    • Generics Functions generic<typename T> where T:IDog void DoAll(T t) { t->Bark(0); t->WagTail(); } *http://www.codeproject.com/managedcpp/cppcligenerics.asp
    • Template vs. Generics
      • Templates are instantiated at compile-time with the source code.
      • The type checking of a template are performed at the point where the template is defined and instantiated .
      • Tempaltes allow specialization.
      • Templates allow non-type parameters.
      • Templates use &quot; lazy structural constraints &quot;.
      • Generics are instantiated at run-time by the CLR.
      • The type checking of a generic is peformend at the point where the generic is defined .
      • Generics are cross-language .
      • Generics do not allow specialization.
      • Generics do not allow non-type parameters.
      • Generics use subtype constraints .
      *http://blogs.msdn.com/branbray/archive/2003/11/19/51023.aspx
    • Verifiable C++
      • 以 /clr:safe 編譯,將會試著產生 verifiable assembly
      • 若使用了不安全的語法時,將會得到錯誤訊息
        • 例如,不能使用指標運算
      • 諸如 tempaltes, deterministic destruction 其他功能則是安全的
    • 使用程式庫
      • 使用 managed assembly : #using
        • #using <System.Data.dll>
      • 使用 COM 元件: #import
        • #using <msxml4.dll>
      • 使用 Standard C++ Library : #include
        • #include <iostream>
    • C++/CLI 的標準化現況
      • C++/CLI 在 2005 年 12 月已經成為國際標準( ECMA 372 )
    • Reference
      • Hello C++/CLI
        • http://msdn.microsoft.com/msdnmag/issues/06/00/PureC/default.aspx
      • ECMA-372 : C++/CLI Language Specification
        • http://www.ecma-international.org/publications/standards/Ecma-372.htm
      • void Nish(char *szBlog)
        • http://blog.voidnish.com/index.php?cat=2
      • The Code Project
        • http://www.codeproject.com/managedcpp/#C%2B%2B%2FCLI
    • Thanks