【4opencv】CLR基本原理和如何运用于GOCW
GOCW的重点和难点就在于Csharp调用OpenCV,其中的桥梁就是CLR,当然我们也有其他方法,但是CLR是一个比较新的、比较可靠的、关键是能用的桥梁。这里关于CLR的基本原理知识、如何用于GOCW项目的相关内容加以整理思考,以图深入:
1、什么是CLR
CLR(Common Language Runtime)是“公共语言运行时”的缩写,简单来说它是和Java虚拟机一样的一个运行时环境。它负责资源管理(内存分配和垃圾收集),并保证应用和底层操作系统之间必要的分离。
通用语言运行时是.NET 框架应用程序的执行引挚。它提供了许多服务,其中包括:代码管理(装入和执行)、类型安全性验证、元数据(高级类型信息)访问、为管理对象管理内存、管理代码,COM对象和预生成的DLLs(非管理代码和数据)的交互操作性、对开发人员服务的支持等等。
我们GOCW项目中为了能够使用Csharp调用OpenCV,采用了托管C++;
2、什么是托管C++?
托管是.NET的一个专门概念,它是融于通用语言运行时(CLR)中的一种新的编程理念,使用托管C++意味着,我们的代码可以被CLR所管理,并能开发出具有最新特性如垃圾自动收集、程序间相互访问等的.NET框架应用程序。
由托管概念所引发的C++应用程序包括托管代码、托管数据和托管类三个组成部分。
(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关键字的类。
3、托管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;
}
- Scan0:数据矩阵在内存中的地址。
- Stride:数据矩阵中的行宽,以byte为单位。可能会扩展几个Byte,后面会介绍。
- PixelFormat:像素格式,这对矩阵中字节的定位很重要。
- Width:位图的宽度。
- Height:位图的高度。
具体关系见下图:
- 32位RGB:假设X、Y为位图中像素的坐标,则其在内存中的地址为scan0+Y*stride+X*4。此时指针指向蓝色,其后分别是绿色、红色,alpha分量。
- 24位RGB:scan0+Y*stride+X*3。此时指针指向蓝色,其后分别是绿色和红色。
- 8位索引:scan0+Y*stride+X。当前指针指向图像的调色盘。
- 4位索引:scan0+Y*stride+(X/2)。当前指针所指的字节包括两个像素,通过高位和低位索引16色调色盘,其中高位表示左边的像素,低位表示右边的像素。
- 1位索引:scan0+Y*stride+X/8。当前指针所指的字节中的每一位都表示一个像素的索引颜色,调色盘为两色,最左边的像素为8,最右边的像素为0。(TODO EMGUCV ISSUE)
//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");
最新文章
- chain.doFilter(request,response)含义
- Spring详细总结
- [Spring] - Spring + Hibernate
- [WinAPI] API 1 [桌面上画一个简单彩色图形]
- sdut 2153 Clockwise (2010年山东省第一届ACM大学生程序设计竞赛)
- hdu 1087
- 解读eXtremeComponents代码结构--转载
- 2016041601 - linux上安装maven
- C++下字符串转换
- 绩效考核指标KPI 听课笔记
- (转)Memcached 在windows下的java使用
- 递归调用里的性能问题(js)
- viim命令行模式查找替换
- openstack安装系列问题:window7 64位安装的virtualBox 只能选择32位的系统安装不能选择64位的系统安装
- SpringMVC, Spring和Mybatis整合案例一
- LwIP Application Developers Manual10---LwIP IPv4/IPv6 stacks
- CRM 2016 执行IFrame 子页面中函数
- shell脚本中特定符合变量的含义
- python 矩阵转置
- Java数组声明与拷贝的几种方式
热门文章
- PHP判断ip地址是否合法
- Winform下如何上传图片并显示出来。同时保存到数据库
- 记工作中用到的抓取oracle表结构的sql语句
- 《大话设计模式》c++实现 模版方法模式
- JavaScript--定时器setTimeout()、clearTimeout(var param)和setInterval()、clearInterval(var param)
- Born Slippy (超大背包问题 + 树形DP)
- mysql运用now(3)存储时间到毫秒
- python 内置函数 sorted()
- 只打开一次浏览器,生成html测试报告<;小紧张中......>;
- interface接口——公共规范标准