C#調用C++ DLL類方法


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++寫的類了.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM