C++的優勢在於高效靈活,C#的優勢在於簡單易用,兩者結合起來對項目開發來說是件好事,而且C++不容易反編譯,也保障了代碼的安全性,如果一些核心算法使用C#編寫,那么保密就是一個問題。 C++生成的DLL一般只提供函數接口,不能直接用C#調用C++寫的類,這樣非常不方便,於是經過半天的反復測試,終於確定了一套可行的方案,下面就是整個流程的一個范例。 (1)編寫C++類Mask,類前面的extern "C" class _declspec(dllexport)這么一串修飾符是必備的,不然無法導出類。 [cpp] view plain copy print? //Mask類頭文件mask.h #pragma once extern "C" class _declspec(dllexport) Mask { public: Mask(char* inputFile,int* maskValue,int maskLength); virtual void Run(void); ~Mask(void); private: char* _inputFile; int* _maskValue; int _maskLength; }; (2)Mask類內部實現,這里使用char*和int*這兩個有代表性的參數,C#向C++進行參數的傳遞是很難弄的一步。 [cpp] view plain copy print? //Mask類實現文件mask.cpp Mask::Mask(char* inputFile ,int* maskValue,int maskLength) { _inputFile=new char[strlen(inputFile)+1]; strcpy(_inputFile,inputFile); _maskValue=new int[maskLength]; _maskLength=maskLength; for(int i=0;i<maskLength;i++) _maskValue[i]=maskValue[i]; } void Mask::Run(void) { } Mask::~Mask(void) { if (_inputFile) { delete [] _inputFile; _inputFile=NULL; } if (_maskValue) { delete [] _maskValue; _maskValue=NULL; } } 可以設置生成類型為DLL,然后將debug目錄下的dll文件和lib文件找到,留待下一步使用。 (3)編寫C++.NET類MaskCLR,C++.NET我一直認為就是個擺設,沒想到也能派上用場,難得啊,也不完全是個廢物。MaskCLR可以調用Mask類,注意函數的參數已經變成String ^和int*,現在是.NET環境,使用指針沒那么方便了。 [cpp] view plain copy print? //MaskCLR類頭文件,用來包裝Mask類MaskCLR.h #pragma once #include " mask.h" //這個就是上面的Mask頭文件 public ref class MaskCLR { private: char* _inputFile; int* _maskValue; int _maskLength; public: MaskCLR(String ^ inputFile,int* maskValue,int maskLength); virtual void Run(void) override; }; (4)MaskCLR類內部實現,首先要處理參數類型問題,將String ^類型轉為char*。在MaskCLR:: Run函數內部調用Mask類,Mask是DLL導出的類。 [cpp] view plain copy print? // MaskCLR類內部實現MaskCLR.cpp #include "MaskCLR.h" MaskCLR::MaskCLR(String ^ inputFile,int* maskValue,int maskLength) { _inputFile=GlobeFunction::StringToChar(inputFile); _maskValue=maskValue; _maskLength=maskLength; } void MaskCLR:: Run(void) { Mask mask(_inputFile, _maskValue,_maskLength); mask.Run(); } (5)將String ^類型轉為char*,可以利用StringToHGlobalAnsi這個.NET自帶的函數。 [csharp] view plain copy print? char* GlobeFunction::StringToChar(String ^str) { return (char*)(Marshal::StringToHGlobalAnsi(str)).ToPointer(); } (6)最終生成了兩個DLL文件,一個是原始C++編寫的,另一個是托管C++編寫的,托管dll只是個外殼,最終還是調用原始dll,因此這兩個dll要放在一起。下面終於進入C#環境了,首先將托管dll添加引用到C#工程中,C++.NET和C#可以直接互用。 (7)由於有個int*類型參數,在C#里指針屬於不安全代碼,因此使用unsafe關鍵字將涉及到指針的代碼包括起來,在工程屬性里設置允許使用不安全代碼。定義int指針需要使用stackalloc關鍵字,創建一個int數組,對數組賦值后,將指針傳遞給類函數。 [csharp] view plain copy print? //c#調用托管dll中的MaskCLR類form1.cs unsafe { int* value = stackalloc int[1]; value[0] = 0; MaskCLR mask = new MaskCLR("D:\\臨時\\mask8.tif", value, 1); mask.Run(); } (8)至此大功告成,可以用C#很方便的調用C++寫的類了.