使用者工具

網站工具


programming:dot_net_framework

差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

下次修改
前次修改
programming:dot_net_framework [2013/07/19 16:32]
wenpei 建立
programming:dot_net_framework [2013/07/29 16:42] (目前版本)
wenpei
行 4: 行 4:
  
 整個架構就差不多是這樣: 整個架構就差不多是這樣:
-  * UI - C#+  * UI - C# Console
   * Wrapper - Visuall C++ CLR Class Library   * Wrapper - Visuall C++ CLR Class Library
   * Kernel - COM DLL   * Kernel - COM DLL
行 17: 行 17:
 首先建立新的 Solution,選擇 Visual C++ → CLR → Class Library 首先建立新的 Solution,選擇 Visual C++ → CLR → Class Library
  
-接著建立 C# 的 UI Project,在 Solution Explorer 視窗裡面的 Solution '​CLRTest'​ 上按滑鼠右鍵 → Add → New Project+{{:​programming:​createclrproject.png?​nolink&​640|}}
  
-完成後 ​Solution Explorer ​應該會長+接著建立 C# 的 Console Project,在 ​Solution Explorer ​視窗裡面的 Solution '​CLRTest'​ 上按滑鼠右鍵 → Add → New Project 
 + 
 +{{:​programming:​createuiproject.png?​nolink&​640|}} 
 + 
 +邊 UI 的部分看是要選 Console Application 或是 Windows Forms Application 都可以。
  
 接著在 C# 的 Project 上按滑鼠右鍵 -> Add Reference 接著在 C# 的 Project 上按滑鼠右鍵 -> Add Reference
 +
 +{{:​programming:​solutionexplorer_addref.png?​nolink|}}
  
 選擇 Project 分頁,然後選擇剛剛建立的 CLR Project 選擇 Project 分頁,然後選擇剛剛建立的 CLR Project
 +
 +{{:​programming:​addrefproject.png?​nolink|}}
  
 完成後應該就可以在 C# Project 的 References 裡面看到 CLR 的 Project 完成後應該就可以在 C# Project 的 References 裡面看到 CLR 的 Project
 +
 +{{:​programming:​addref_finished.png?​nolink|}}
  
 ==== CLR Class Library ==== ==== CLR Class Library ====
-在完成 Project 的建立之後,就可以開始寫 CLR Class 裡面所需要的功能,像是把 COM DLL 讀進來用,或是寫只有在 C++ 才能用的 Windows Imaging Component (WIC) 等等。+在完成 Project 的建立之後,就可以開始寫 CLR Class 裡面所需要的功能,像是把 COM DLL 讀進來用,或是寫只有在 C++ 才能用的 ​[[http://​msdn.microsoft.com/​en-us/​library/​windows/​desktop/​ee719902%28v=vs.85%29.aspx|Windows Imaging Component (WIC)]] 等等。
  
 這邊範例先增加兩個簡單的功能:Add、Minus 這邊範例先增加兩個簡單的功能:Add、Minus
行 69: 行 79:
 } }
 </​code>​ </​code>​
 +
 +完成後即可編譯 CLR Project,生出 Debug\CLRTest.dll 檔案。
 +
 +這時用 Object Browser 打開 CLR Project,應該可以看到 Class 裡面有兩個 function 可以使用。
 +
 +{{:​programming:​objbrowser.png?​nolink|}}
 +
 +==== C# ====
 +建立好 CLR Project 後,在 C# 就可以很方便的直接拿來用
 +
 +<​code>​
 +using System;
 +
 +using CLRTest;
 +
 +namespace CLRTestConsole
 +{
 +    class Program
 +    {
 +        static void Main(string[] args)
 +        {
 +            CLRTestClass clr = new CLRTestClass();​
 +            Console.WriteLine("​3+2="​ + clr.Add(3, 2));
 +            Console.WriteLine("​3-2="​ + clr.Minus(3,​ 2));
 +        }
 +    }
 +}
 +</​code>​
 +
 +若編譯錯誤,可能是平台問題,打開 C# Project 的 Properties,在 Build Tab 裡面的 Platform target 選擇 x86
 +
 +{{:​programming:​clr_x86.png|}}
 +
 +==== 進階應用 ====
 +CLR 的特色之一就是可以直接拿 .Net Framework 的東西來用,因此要和 C# 互通特別容易,像是在 CLR 層將一張圖片檔案透過 GDI+ 打開,接著轉成 Byte Array 給 COM DLL 使用。
 +
 +例如,COM DLL 內定義一個 buffer pointer 為
 +  BYTE *pBuffer;
 +
 +在 CLR 層定義需要用到的類別
 +
 +<​code>​
 +#using <​system.drawing.dll>​
 +using namespace System;
 +using namespace System::​Drawing;​
 +using namespace System::​Drawing::​Imaging;​
 +</​code>​
 +
 +將放在 path 的圖片打開:
 +
 +  Bitmap^ srcBitmap = gcnew Bitmap(path);​
 +
 +透過 Bitmap.LockBits() 固定住記憶體位址,創建一塊 array<​Byte>​ 記憶體空間,並將 Bitmap 的內容複製過去,最後用 pin_ptr 取得 pointer address,這樣就可以指定給 pBuffer 了!並且在 LockBits 使用完之後,記得要 UnlockBits。
 +
 +<​code>​
 + BitmapData^ srcBitmapData = srcBitmap->​LockBits(System::​Drawing::​Rectangle(0,​ 0, srcBitmap->​Width,​ srcBitmap->​Height),​ ImageLockMode::​ReadWrite,​ PixelFormat::​Format32bppArgb);​
 + IntPtr ptr = srcBitmapData->​Scan0;​
 + int bytes = Math::​Abs(srcBitmapData->​Stride) * srcBitmapData->​Height;​
 + array<​Byte>​^ rgbValues = gcnew array<​Byte>​(bytes);​
 + System::​Runtime::​InteropServices::​Marshal::​Copy(ptr,​ rgbValues, 0, bytes);
 + pin_ptr<​Byte>​ p = &​rgbValues[0];​
 + Byte* np = p;
 + pBuffer = np;
 +
 + // ......
 +
 + srcBitmap->​UnlockBits(srcBitmapData);​
 +</​code>​
 +
 +另外一個應用就是把 UI 建立好的 Bitmap 傳到 wrapper 層,轉換成 array<​Byte>​ 後,再傳給 COM DLL 去把圖片放進去,這樣就可以直接把底層修改好的圖片顯示在 UI 上。
 +
 +CLR 層的寫法是透過 Bitmap^% 取得一個 Bitmap 的 handle,並先產生好一塊 Byte Array 空間,COM DLL 修改完 Byte Array 後,複製到傳入的 Bitmap Handle
 +
 +關於 **^%** 的用法可參考 [[http://​stackoverflow.com/​questions/​6616599/​does-the-symbol-replace-cs-ref-in-parameter-passing-in-c-cli-code|Does the ^ symbol replace C#'s “ref” in parameter passing in C++/CLI code?​]] ​
 +
 +<​code>​
 +void CLRTestClass::​SetBitmap(int temperature,​ int tint, Bitmap^% outputBitmap)
 +{
 + BitmapData^ oBitmapData = outputBitmap->​LockBits(System::​Drawing::​Rectangle(0,​ 0, outputBitmap->​Width,​ outputBitmap->​Height),​ ImageLockMode::​ReadWrite,​ PixelFormat::​Format32bppArgb);​
 + int bytes = Math::​Abs(oBitmapData->​Stride) * oBitmapData->​Height;​
 + array<​Byte>​^ outputBuffer = gcnew array<​Byte>​(bytes);​
 + pin_ptr<​Byte>​ oPin = &​outputBuffer[0];​
 + Byte* pOPin = oPin;
 +
 + // 交由 COM DLL 修改內容...
 +
 + IntPtr oPtr = oBitmapData->​Scan0;​
 + System::​Runtime::​InteropServices::​Marshal::​Copy(outputBuffer,​ 0, oPtr, bytes);
 + outputBitmap->​UnlockBits(oBitmapData);​
 +</​code>​
 +
 +C# 層的寫法則是先產生好一個 Bitmap,透過 ref Bitmap 的方式傳給 CLR 直接改記憶體內容,完成後即可用 PictureBox 顯示圖片
 +
 +<​code>​
 +Bitmap bmPic = new Bitmap(openFileDialog1.FileName);​
 +clImgRetouch.SetWhiteBalance(ref bmPic);
 +pictureBox1.Image = (Image)bmPic;​
 +</​code>​
 +
 +==== 參考文件 ====
 +C# Pass by Reference to CLR
 +  * [[http://​msdn.microsoft.com/​en-us/​library/​8903062a%28VS.90%29.aspx|% (Tracking Reference)]]
 +  * [[http://​msdn.microsoft.com/​en-US/​library/​yk97tc08%28v=vs.90%29.aspx|^ (Handle to Object on Managed Heap)]]
 +  * [[http://​msdn.microsoft.com/​en-US/​library/​te3ecsc8%28v=vs.90%29.aspx|gcnew]]
 +  * [[http://​msdn.microsoft.com/​en-us/​library/​1dz8byfh%28v=vs.90%29.aspx|pin_ptr]]
 +  * [[http://​bobpowell.net/​lockingbits.aspx|Using the LockBits method to access image data]]
 +
 +WIC
 +  * [[http://​msdn.microsoft.com/​en-us/​library/​windows/​desktop/​ff973956.aspx|Using the Windows Imaging Component]]
 +
 +COM
 +  * [[http://​msdn.microsoft.com/​zh-tw/​library/​aa288455%28v=vs.71%29.aspx|COM Interop 第 1 部份:C# 用戶端教學課程]]
 +  * [[http://​www.codeproject.com/​Articles/​38254/​A-Beginner-Tutorial-for-Writing-Simple-COM-ATL-DLL|A Beginner Tutorial for Writing Simple COM/ATL DLL and Using it with .NET]]
 +
programming/dot_net_framework.1374222747.txt.gz · 上一次變更: 2013/07/19 16:32 由 wenpei