利用 C++ Interop 封裝 ISO C++ 對象, 供其餘 .Net 語言使用

     .Net BCL 支持兩種互操做技術,模塊 級重用 P/Invoke 和組件級重用COM 互操做,html

 

C++/CLI 除了支持以上兩種互操做之外,更支持代碼級重用, 稱爲 C++ Interop,本文ios

 

僅舉例說明這種互操做技術。本例使用 ISO C++ 創建一個類 NativeLib, 計算並打印編程

 

兩個位置的直線距離,而後使用 C++/CLI 封裝在一個 NativeLibWrap 託管類裏,提this

 

供給 C# 主程序調用。spa

 

// NativeLib.h (ISO C++)指針

#include <iostream>htm

#include <cmath>對象

using namespace std;blog

 

public struct Location內存

{

    Location(double x, double y) : X(x), Y(y) { }

    double X;

    double Y;

};

 

public class NativeLib

{

public:

    NativeLib(Location&, Location&);

    void PrintDistance() const;

private:

    Location firstLocation;

    Location secondLocation;

    double GetDistance() const;

};

 

// NativeLib.cpp (ISO C++)

#include "NativeLib.h"

 

NativeLib::NativeLib(Location& firstLocation, Location& secondLocation) :

    firstLocation(firstLocation), secondLocation(secondLocation) {

}

 

double NativeLib::GetDistance() const {

    double dx = firstLocation.X - secondLocation.X;

    double dy = firstLocation.Y - secondLocation.Y;

    double distance = sqrt(dx * dx + dy * dy);

   

    return distance;

}

 

void NativeLib::PrintDistance() const {

    cout << "The distance is " << GetDistance() << endl;

}

 

以上是 ISO C++ 代碼,要在爲了在託管平臺 下使用,定義一個包裝類 NativeLibWrap

 

它引用一個 NativeLib ISO C++)對象的指針,注意一個託管 對象不能直接包含一

 

個本地(ISO C++)對象,只能使用指針,這是 由垃圾收集機制決定的,本地堆內存屬於

 

非託管資源,所以 NativeLibWrap 類實現了 Dispose 模式,請參考個人另外一篇博客

 

—— .Net Dispose 模式與 C++/CLI 肯定性資源清理

 

// NativeLibWrap.h (C++/CLI)

#pragma once

#include "NativeLib.h"

 

public value struct LocationWrap

{

    LocationWrap(double x, double y) : X(x), Y(y) { }

    double X;

    double Y;

};

 

public ref class NativeLibWrap

{

public:

    NativeLibWrap(LocationWrap, LocationWrap);

    ~NativeLibWrap();

    void PrintDistance();

protected:

    !NativeLibWrap();

private:

    NativeLib* nativeLib;

};

 

// NativeLibWrap.cpp (C++/CLI)

#incude "NativeLibWrap.h"

 

NativeLibWrap::NativeLibWrap(LocationWrap firstLocationWrap, LocationWrap secondLocationWrap) {

    Location firstLocation(firstLocationWrap.X, firstLocationWrap.Y);

    Location secondLocation(secondLocationWrap.X, secondLocationWrap.Y);

    this->nativeLib = new NativeLib(firstLocation, secondLocation);

}

 

NativeLibWrap::~NativeLibWrap() {

    this->!NativeLibWrap();

}

 

NativeLibWrap::!NativeLibWrap() {

    delete nativeLib;

}

 

void NativeLibWrap::PrintDistance() {

    this->nativeLib->PrintDistance();

}

 

Compile the four files with:

cl /clr /LD NativeLibWrap.cpp NativeLib.cpp

將產生NativeLibWrap.dll

 

// NativeLibWrapTest.cs (C#)

internal static class NativeLibWrapTest

{

    private static void Main() {

        LocationWrap firstLocation = new LocationWrap(1, 1);

        LocationWrap secondLocation = new LocationWrap(4, 5);

        NativeLibWrap nativeLibWrap = new NativeLibWrap(firstLocation, 

            secondLocation);

        nativeLibWrap.PrintDistance();

        nativeLibWrap.Dispose();

    }

}

 

Compile with:

csc /r:NativeLibWrap.dll NativeLibWrapTest.cs

輸出NativeLibWrapTest.exe

 

運行, 輸出The distance is 5

 

    對於ISO C++ 自定義的struct, enum 等類型,爲了在其餘.Net 語言中調用,須要從新定義爲

 

value struct (value class), enum class 等,若是隻是在C++/CLI中使用,則不須要從新定

 

義,由於C++/CLI 支持ISO C++ 與託管代碼的混合編程。

 

    C++/CLI 也支持在本地類型中訪問託管對象,須要使用gcroot 模板,也比較簡單,能夠查閱MSDN

     

相關文檔說明,本文再也不綴述。

相關文章
相關標籤/搜索