基于.NET的托管C++开发

1. 简介

随着Windows的发展,基于.Net的功能越来越多,使用也越来越方便。早期的.Net主要是C#和VB.NET进行开发。Windows希望几种主要的语言都能够统一,大家互相调用。Windows提供了CLR(Common Language Runtime),来统一各语言编译后的标准。另外还提供了.Net库,包括非常多的相关.Dll,提供功能API供调用。

2. 托管C++基本语法

托管,意味着内存的申请释放都统一交给CLR来处理。所以托管C++扩展了标准C++,提供了托管类。.NET中,所有类型都是对象类型。所以C++调用.NET中的API,都必须使用托管类型,以保持匹配。

2.1. 托管C++类型

2.1.1. 字符串

c#中的字符串
String str = “abc”;
托管C++中调用.NET字符串
String^ str = “abc”;
std::string strVal = “abc”;
托管字符串与标准字符串相互转换
String^ stdVal = marshal_as<String^>(strVal);
std::string strNew = marshal_asstd::string(stdVal);

2.1.2. 数组

c#中数组也是对象类型
String[] strArr = {“abc”, “bc”, “dd”};
托管C++调用.NET中数组类型
array<System::String > strArr = {“abc”, “abc”};
// gcnew,托管堆上申请内存,由托管自动管理释放
array<System::String > strArr1 = gcnew array<String^>(1) { “a” };
// 托管类型类似于指针,获批数组大小
int nCount = strArr->Length;

2.1.3. 基本类型

.NET中int等也有相应的对象类型
System.Int32 a;
System.Int16 b;

2.2. 调用

2.2.1. 引用

void Test(int % i) {
i++;
}
String^% stdValRef = stdVal;

2.2.2. 调用

.NET中大量使用命令空间。
C#调用
Console.WriteLine(“Hello world!”);
托管C++中
Console::WriteLine(“Hello world!”);

3. 示例

3.1. 调用.NET中的VisualStudio

VS2010中的coverage文件转成xml文件,需要用到.NET的功能。
C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.VisualStudio.Coverage.Analysis;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 3)
            {
                Console.WriteLine("Transform the coverage file to xml file.\r\n" + 
                                   "\r\n" + 
                                   "Coverage2xml coveragePath dllDir xmlPath\r\n" +
                                   "    coveragePath: xx.coverage file path.\r\n" + 
                                   "    dllPath:      the directory of unit test project's dll.\r\n" + 
                                   "    xmlPath:      the xml path for output.\r\n" + 
                                   "\r\n" + 
                                   "example: Coverage2xml e:\\data.coverage e:\\debug e:\\xx.xml");
                return;
            }

            string coveragePath = args[0];
            string dllDir = args[1];
            string xmlPath = args[2];
            using (CoverageInfo info = CoverageInfo.CreateFromFile(coveragePath, new string[] { dllDir }, new string[] { dllDir }))
            {
                CoverageDS data = info.BuildDataSet();
                data.WriteXml(xmlPath);
            }
        }
    }
}

托管C##代码:

#include <iostream>
using namespace System;
using namespace System::Collections;
using namespace Microsoft::VisualStudio::Coverage::Analysis;


int main(array<System::String ^> ^args)
{
	if (args->Length < 3)
	{
		Console::WriteLine("Transform the coverage file to xml file.\r\n" + 
			"\r\n" + 
			"Coverage2xml coveragePath dllDir xmlPath\r\n" +
			"    coveragePath: xx.coverage file path.\r\n" + 
			"    dllPath:      the directory of unit test project's dll.\r\n" + 
			"    xmlPath:      the xml path for output.\r\n" + 
			"\r\n" + 
			"example: Coverage2xml e:\\data.coverage e:\\debug e:\\xx.xml");
		return 0;
	}

	String^ a = gcnew String("abc");

	String^ coveragePath = args[0];
	String^ dllDir = args[1];
	String^ xmlPath = args[2];
	CoverageInfo^ info = CoverageInfo::CreateFromFile(coveragePath, gcnew array<String^>(1) { dllDir }, gcnew array<String^>(1){dllDir });
	{
		CoverageDS^ data = info->BuildDataSet();
		data->WriteXml(xmlPath);
	}

    return 0;
}

3.2. 调用.NET中的Excel

C#代码:

using System;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel; 

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Excel.Application xlApp ;
            Excel.Workbook xlWorkBook ;
            Excel.Worksheet xlWorkSheet ;
            object misValue = System.Reflection.Missing.Value;

            xlApp = new Excel.Application();
            xlWorkBook = xlApp.Workbooks.Add(misValue);
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

            //add data 
            xlWorkSheet.Cells[1, 1] = "";
            xlWorkSheet.Cells[1, 2] = "Student1";
            xlWorkSheet.Cells[1, 3] = "Student2";
            xlWorkSheet.Cells[1, 4] = "Student3";

            xlWorkSheet.Cells[2, 1] = "Term1";
            xlWorkSheet.Cells[2, 2] = "80";
            xlWorkSheet.Cells[2, 3] = "65";
            xlWorkSheet.Cells[2, 4] = "45";

            xlWorkSheet.Cells[3, 1] = "Term2";
            xlWorkSheet.Cells[3, 2] = "78";
            xlWorkSheet.Cells[3, 3] = "72";
            xlWorkSheet.Cells[3, 4] = "60";

            xlWorkSheet.Cells[4, 1] = "Term3";
            xlWorkSheet.Cells[4, 2] = "82";
            xlWorkSheet.Cells[4, 3] = "80";
            xlWorkSheet.Cells[4, 4] = "65";

            xlWorkSheet.Cells[5, 1] = "Term4";
            xlWorkSheet.Cells[5, 2] = "75";
            xlWorkSheet.Cells[5, 3] = "82";
            xlWorkSheet.Cells[5, 4] = "68";

            Excel.Range chartRange ; 

            Excel.ChartObjects xlCharts = (Excel.ChartObjects)xlWorkSheet.ChartObjects(Type.Missing);
            Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 80, 300, 250);
            Excel.Chart chartPage = myChart.Chart;

            chartRange = xlWorkSheet.get_Range("A1", "d5");
            chartPage.SetSourceData(chartRange, misValue);
            chartPage.ChartType = Excel.XlChartType.xlColumnClustered; 

            xlWorkBook.SaveAs("csharp.net-informations.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
            xlWorkBook.Close(true, misValue, misValue);
            xlApp.Quit();

            releaseObject(xlWorkSheet);
            releaseObject(xlWorkBook);
            releaseObject(xlApp);

            MessageBox.Show("Excel file created , you can find the file c:\\csharp.net-informations.xls");
        }

        private void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }
    }
}

托管C++代码:

using namespace System;
using namespace System::Collections;
using namespace Microsoft::VisualStudio::Coverage::Analysis;
using namespace Microsoft::Office::Interop::Excel; 



void TestExcel()
{
	System::Object^ misValue = System::Reflection::Missing::Value;

	Microsoft::Office::Interop::Excel::Application^ xlApp = gcnew Microsoft::Office::Interop::Excel::Application();
	Microsoft::Office::Interop::Excel::Workbook^ xlWorkBook = xlApp->Workbooks->Add(misValue);
	Microsoft::Office::Interop::Excel::Worksheet^ xlWorkSheet = (Microsoft::Office::Interop::Excel::Worksheet^)xlWorkBook->Worksheets[1];

	xlWorkSheet->Cells[1, 1] = "";
	xlWorkSheet->Cells[1, 2] = "Student1";
	xlWorkSheet->Cells[1, 3] = "Student2";
	xlWorkSheet->Cells[1, 4] = "Student3";

	xlWorkSheet->Cells[2, 1] = "Term1";
	xlWorkSheet->Cells[2, 2] = "80";
	xlWorkSheet->Cells[2, 3] = "65";
	xlWorkSheet->Cells[2, 4] = "45";

	xlWorkSheet->Cells[3, 1] = "Term2";
	xlWorkSheet->Cells[3, 2] = "78";
	xlWorkSheet->Cells[3, 3] = "72";
	xlWorkSheet->Cells[3, 4] = "60";

	xlWorkSheet->Cells[4, 1] = "Term3";
	xlWorkSheet->Cells[4, 2] = "82";
	xlWorkSheet->Cells[4, 3] = "80";
	xlWorkSheet->Cells[4, 4] = "65";

	xlWorkSheet->Cells[5, 1] = "Term4";
	xlWorkSheet->Cells[5, 2] = "75";
	xlWorkSheet->Cells[5, 3] = "82";
	xlWorkSheet->Cells[5, 4] = "68";

	Microsoft::Office::Interop::Excel::ChartObjects^ xlCharts = (Microsoft::Office::Interop::Excel::ChartObjects^)xlWorkSheet->ChartObjects(Type::Missing);
	Microsoft::Office::Interop::Excel::ChartObject^ myChart = (Microsoft::Office::Interop::Excel::ChartObject^)xlCharts->Add(10, 80, 300, 250);
	Microsoft::Office::Interop::Excel::Chart^ chartPage = myChart->Chart;

	Microsoft::Office::Interop::Excel::Range^ chartRange = xlWorkSheet->Range::get("A1", "d5");
	chartPage->SetSourceData(chartRange, misValue);
	chartPage->ChartType = Microsoft::Office::Interop::Excel::XlChartType::xlColumnClustered; 

	xlWorkBook->SaveAs("e:\\csharp.net-informations.xls", Microsoft::Office::Interop::Excel::XlFileFormat::xlWorkbookNormal, misValue, misValue, misValue, misValue, Microsoft::Office::Interop::Excel::XlSaveAsAccessMode::xlExclusive, misValue, misValue, misValue, misValue, misValue);
	xlWorkBook->Close(true, misValue, misValue);
	xlApp->Quit();

	System::Runtime::InteropServices::Marshal::ReleaseComObject(xlWorkSheet);
	System::Runtime::InteropServices::Marshal::ReleaseComObject(xlWorkBook);
	System::Runtime::InteropServices::Marshal::ReleaseComObject(xlApp);
	GC::Collect();
}

完整示例见附件

4. 托管与非托管

托管C++有特殊的语法,编译的规则也有变化,默认生成的接口与标准C++不兼容。
如果在托管C++中想使用标准C++编译,可以使用
#pragma unmanaged和#pragma managed

4.1. 非托管封装托管代码

创建一个CLR的DLL工程,在其中添加如下代码,就可以导出标准C++的接口供标准C++工程使用了。完整示例见附件

// .h
#pragma once

#pragma unmanaged

#ifdef TT_EXPORTS
#define TT_API __declspec(dllexport)
#else
#define TT_API __declspec(dllimport)
#endif

class TT_API Calc
{
public:
	Calc(void);

	int Add(int a, int b);
};

#pragma managed
// .cpp
#include "StdAfx.h"
#include "Calc.h"
#include <string>

#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>
using namespace System;
using namespace System::Collections;;
using namespace msclr::interop;

void Test(std::string str)
{
	String^ stdToCli = marshal_as<String^>(str);
	Console::WriteLine(stdToCli);
}

#pragma unmanaged

Calc::Calc(void)
{
}

int Calc::Add(int a, int b)
{
	Test("Hello World!");
	return a+b;
}

#pragma managed
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值