一、什麼是CLRc++
CLR(Common Language Runtime)是「公共語言運行時」的縮寫,簡單來講它是和Java虛擬機同樣的一個運行時環境。它負責資源管理(內存分配和垃圾收集),並保證應用和底層操做系統之間必要的分離。編程
通用語言運行時是.NET 框架應用程序的執行引摯。它提供了許多服務,其中包括:代碼管理(裝入和執行)、類型安全性驗證、元數據(高級類型信息)訪問、爲管理對象管理內存、管理代碼,COM對象和預生成的DLLs(非管理代碼和數據)的交互操做性、對開發人員服務的支持等等。c#
咱們GOCW項目中爲了可以使用Csharp調用OpenCV,採用了託管C++;數組
二、什麼是託管C++?安全
託管是.NET的一個專門概念,它是融於通用語言運行時(CLR)中的一種新的編程理念,使用託管C++意味着,咱們的代碼能夠被CLR所管理,並能開發出具備最新特性如垃圾自動收集、程序間相互訪問等的.NET框架應用程序。框架
由託管概念所引起的C++應用程序包括託管代碼、託管數據和託管類三個組成部分。 ide
(1) 託管代碼:. Net環境提供了許多核心的運行(RUNTIME)服務,好比異常處理和安全策略。爲了能使用這些服務,必需要給運行環境提供一些信息代碼(元數據),這種代碼就是託管代碼。全部的C#、VB.NET、JScript.NET默認時都是託管的,但Visual C++默認時不是託管的,必須在編譯器中使用命令行選項(/CLR)才能產生託管代碼。函數
(2) 託管數據:與託管代碼密切相關的是託管數據。託管數據是由公共語言運行的垃圾回收器進行分配和釋放的數據。默認狀況下,C#、Visual Basic 和 JScript.NET 數據是託管數據。不過,經過使用特殊的關鍵字,C# 數據能夠被標記爲非託管數據。Visual C++數據在默認狀況下是非託管數據,即便在使用 /CLR 開關時也不是託管的。編碼
(3) 託管類: 儘管Visual C++數據在默認狀況下是非託管數據,可是在使用C++的託管擴展時,可使用"__gc"關鍵字將類標記爲託管類。就像該名稱所顯示的那樣,它表示類實例的內存由垃圾回收器管理。另外,一個託管類也徹底能夠成爲 .NET 框架的成員,由此能夠帶來的好處是,它能夠與其餘語言編寫的類正確地進行相互操做,如託管的C++類能夠從Visual Basic類繼承等。但同時也有一些限制,如託管類只能從一個基類繼承等。須要說明的是,在託管C++應用程序中既可以使用託管類也可使用非託管類。這裏的非託管類不是指標準C++類,而是使用託管C++語言中的__nogc關鍵字的類。spa
三、託管C++與標準C++的主要區別
儘管託管C++是從標準C++創建而來的,但它與標準C++有着本質上的區別,這主要體如今如下幾個方面:
(1) 普遍採用"名稱空間"(namespace)
名稱空間是類型的一種邏輯命名方案,.NET使用該命名方案用於將類型按相關功能的邏輯類別進行分組,利用名稱空間可使開發人員更容易在代碼中瀏覽和引用類型。固然,咱們也可將名稱空間理解成是一個"類庫名"。
(2) 基本數據類型的變化
咱們知道,標準C++語言的數據類型是很是豐富的。而託管C++的數據類型更加豐富,不只包含了標準C++中的數據類型,並且新增了__int64 (64位整型)、Decimal(96位十進制數)、String*(字符串類型)和Object*(對象類型)等類型,表1-1列出它們各自數據類型。
(3) 新增三個託管C++類型:__gc class、__value class和__gc interface
一個__gc類或結構意味着該類或結構的生命週期是由.NET開發平臺自動管理及垃圾自動收集,用戶沒必要自已去調用delete來刪除。定義一個__gc類或結構和標準C++基本類似,所不一樣的是在class或struct前加上__gc。
////////將輸入cli::array<unsigned char>轉換爲cv::Mat//////////////////
pin_ptr
<System
:
:Byte
> p1
=
&pCBuf1[
0];
unsigned
char
* pby1
= p1;
cv
:
:Mat img_data1(pCBuf1
-
>Length,
1,CV_8U,pby1);
cv
:
:Mat img_object
= cv
:
:imdecode(img_data1,IMREAD_UNCHANGED);
if (
!img_object.data)
return nullptr;
System
:
:Drawing
:
:Bitmap
^ MatToBitmap(
const cv
:
:Mat
& img)
{
if (img.type()
!= CV_8UC3)
{
throw gcnew NotSupportedException(
"Only images of type CV_8UC3 are supported for conversion to Bitmap");
}
//create the bitmap and get the pointer to the data
PixelFormat fmt(PixelFormat
:
:Format24bppRgb);
Bitmap
^bmpimg
= gcnew Bitmap(img.cols, img.rows, fmt);
BitmapData
^data
= bmpimg
-
>LockBits(System
:
:Drawing
:
:Rectangle(
0,
0, img.cols, img.rows), ImageLockMode
:
:WriteOnly, fmt);
Byte
*dstData
=
reinterpret_cast
<Byte
*
>(data
-
>Scan0.ToPointer());
unsigned
char
*srcData
= img.data;
for (
int row
=
0; row
< data
-
>Height;
++row)
{
memcpy(
reinterpret_cast
<
void
*
>(
&dstData[row
*data
-
>Stride]),
reinterpret_cast
<
void
*
>(
&srcData[row
*img.step]), img.cols
*img.channels());
}
bmpimg
-
>UnlockBits(data);
return bmpimg;
}
具體關係見下圖:
//2.引用傳遞int
int GOClrClass
:
:allTest(
int a,
int b,
int
* c);
int GOClrClass
:
:allTest(
int a,
int b,
int
* c)
{
*c
=a
+b;
return
*c;
}
unsafe
{
int
* value
= stackalloc
int[
1];
value[
0]
=
0;
int iret
= client.allTest(
2,
3, value);
}
System
:
:String
^ GOClrClass
:
:allTestStr(System
:
:String
^ inputStr)
{
System
:
:String
^ retstr
=
"fsdfsdf";
return retstr;
}
string
s
=
client
.
allTestStr
(
"abcdefg"
);