模块化组件化实现独立的功能模块是软件设计的良好习惯,一般用实现为DLL。普通的DLL对外提供接口是采用导出函数接口,如果接口数量不大,只是50个以内,这种方式很适合;如果对外接口有上百个,导出函数接口就完全破坏了软件模块化分层设计的理念,使用接口非常麻烦,此情形采用C++/CLI导出类方式实现比较适合,即核心实现先C++ DLL,然后C++/CLI直接调用C++ DLL导出类,对外第三方工程提供CLI类接口。3种开发语言常用的数据类型对应关系如下表所示:
MFC C++ | C++/CLI | C# | 说明 |
int | int | int | |
bool | bool | bool | |
byte | byte | byte | |
long long | long long | long | |
int& | int% | ref int | int形参返回值 |
HWND | IntPtr | IntPtr | |
CString | String^ | String | |
int | Color | Color | 需在CLI工程写int与Color转换函数 |
long long | DateTime | DateTime | 需在CLI工程写long long 与DateTime转换函数 |
CChart* | CChart* | IntPtr | |
CChart^ | CChart | 都是托管类型对象 | |
CCurve^ | CCurve | 都是托管类型对象 | |
List<CCurve^>^ | List<ChartObject> | 都是托管类型对象 | |
CCurve^% | ref Ccurve | ||
array<Color>^ | Color[] | ||
property | 属性 | 直接属性取值赋值 | |
需要特别说明的是:
1>需要函数形参返回int值时,C++定义为int&,CLI定义为int%,C#定义为ref int。如GetChartSize(int& w, int& h) --> GetChartSize(int% w, int% h) --> GetChartSize(ref int w, ref int h);
2>需要颜色定义时,C++不支持Color只能用int,CLI支持Color,C#支持Color,因为int和Color类型的内存不一样,需要中间层CLI把int 与 Color相互转换(DateTime类型也是如此)。转换函数如下:
1 static UINT32 Color2UInt(Color color) 2 { 3 UINT32 argb = 0; 4 // argb += color.A << 24; 5 argb += color.R << 0; 6 argb += color.G << 8; 7 argb += color.B << 16; 8 return argb; 9 } 10 static Color UInt2Color(UINT32 c) 11 { 12 Color clr; 13 clr = clr.FromArgb((c >> 0) & 255, (c >> 8) & 255, (c >> 16) & 255); 14 return clr; 15 }
![点击并拖拽以移动](/i/l/?n=23&i=blog/2884338/202307/2884338-20230709103140537-1063209359.gif)
3>CLI类加^,等同于C#的类,都是托管对象。
那么C++对象是怎么与C#对应上的呢?他们无法直接对应,得通过CLI层转换。得在CLI层同时维护C++类指针与CLI类引用,并且让他们关联上。对C#使用CCurve^托管对象,对内维护C++类CCurve*指向的非托管内存。具体请看下一节CLI工程源码。
4> 属性的实现。C++使用setXXX和GetXXX函数,CLI使用property即set和get方法,C#直接访问变量。示例如下:
1 //C++工程 LineCurve.h声明 2 int m_nLineWidht; 3 int GetLineWidth(); 4 void SetLineWidth(int w); 5 6 //C++工程 LineCurve.cpp实现 7 int CLineCurve::GetLineWidth() 8 { 9 return m_nLineWidht; 10 } 11 void CLineCurve::SetLineWidth(int w) 12 { 13 m_nLineWidht = w; 14 } 15 16 17 //----------------------------------------------------- 18 //CLI工程 LineCurve.h声明 19 property int LineWidth { 20 int get(); 21 void set(int value); 22 } 23 24 //CLI工程 LineCurve.cpp实现 25 int LineCurve::LineWidth::get() 26 { 27 return m_cLineCurve->GetLineWidth(); 28 } 29 void LineCurve::LineWidth::set(int value) 30 { 31 m_cLineCurve->SetLineWidth(value); 32 } 33 34 35 //----------------------------------------------------- 36 //C#工程 37 LineCurve lcurve = new LineCurve(); 38 lcurve.LineWidth = 3; 39 int lw = lcurve.LineWidth;
![点击并拖拽以移动](/i/l/?n=23&i=blog/2884338/202307/2884338-20230709103140537-1063209359.gif)