因为历史缘由,不少时候咱们的代码并不彻底是使用.NET写成的。这时候和以往C++代码的混合编程就显得至关重要了。最近碰到了这样的问题,将方法简要记述以下。编程
调用简单的C++函数
要在C#代码中调用C++函数,大致的思路是这样的:首先将C++函数写成DLL形式的库,而后在C#中导入DLL中的函数进行调用。具体的代码相似这样:
C++代码:数组
1
int
StaticElementNumber
=
10
;
2
extern
"
C
"
AFX_API_EXPORT
int
GetArrayElementNumber()
3
{
4
return
StaticElementNumber;
5
}
C#代码:
(导入函数部分,写在调用函数所在类中)函数
1
[DllImport(
"
MFCDll.dll
"
)]
2
public
static
extern
int
GetArrayElementNumber();
3
int
ElementNumber
=
GetArrayElementNumber();
s其中的细节,好比int和char等数据类型在C++和C#中占用的空间不一样等等CLR会自动处理。(主要是经过Marshal类自动处理)post
这样的调用还支持调试。打开C#工程的Properties,在Debug选项卡中勾选Enable unmanaged code debugging便可启用C++代码调试。这样在调试模式下,调用这个函数时能够继续按F11跟进函数内部进行调试。spa
传递GDI对象
一些复杂的Windows对象能够经过句柄来传送。好比下面的代码就将一个GDI+ Bitmap对象转换成GDI句柄进行传送。
C++代码(GDI+的声明,引用等等省略):debug
1
extern
"
C
"
AFX_API_EXPORT HBITMAP GetABitmap(WCHAR
*
strFileName)
2
{
3
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
4
ULONG_PTR gdiplusToken;
5
GdiplusStartup(
&
gdiplusToken,
&
gdiplusStartupInput, NULL);
6
Bitmap
*
bitmap
=
Bitmap::FromFile(strFileName);
7
HBITMAP HBitmapToReturn;
8
bitmap
->
GetHBITMAP(NULL,
&
HBitmapToReturn);
9
GdiplusShutdown(gdiplusToken);
10
11
return
HBitmapToReturn;
12
}
C#代码(用户界面采用WPF,略去相关声明和引用):调试
1
[DllImport(
"
MFCDll.dll
"
)]
2
public
static
extern
IntPtr GetABitmap([MarshalAs(UnmanagedType.LPWStr)]
string
strFileName);
3
4
private
void
MenuItemFileOpenOnClicked(
object
sender, RoutedEventArgs e)
5
{
6
OpenFileDialog dialog
=
new
OpenFileDialog();
7
dialog.Title
=
"
Load an image...
"
;
8
dialog.Multiselect
=
false
;
9
if
(dialog.ShowDialog()
==
true
)
10
{
11
mainGrid.Children.Clear();
12
13
IntPtr hBitmap
=
GetABitmap(dialog.FileName);
14
Bitmap bitmap
=
Bitmap.FromHbitmap(hBitmap);
15
System.Windows.Controls.Image image
=
new
Windows.Controls.Image();
16
image.Source
=
Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, ro, Int32Rect.Empty,
17
Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
18
image.Stretch
=
System.Windows.Media.Stretch.Fill;
19
DeleteObject(hBitmap);
20
mainGrid.Children.Add(image);
21
}
22
}
传递数组
传递定长数组很简单,此处不述。下面的代码实现变长数组的传递:
C++代码:code
1
int
StaticElementNumber
=
10
;
2
extern
"
C
"
AFX_API_EXPORT
bool
GetArray(
int
ElementNumber,
double
*
BaseAddress)
3
{
4
if
(ElementNumber
<
StaticElementNumber)
5
{
6
return
false
;
7
}
8
9
for
(
int
i
=
0
; i
<
StaticElementNumber;
++
i)
10
{
11
BaseAddress[i]
=
1
/
((
double
)i
+
1
);
12
}
13
14
return
true
;
15
}
16
17
extern
"
C
"
AFX_API_EXPORT
int
GetArrayElementNumber()
18
{
19
return
StaticElementNumber;
20
}
C#代码: 对象
1
[DllImport(
"
MFCDll.dll
"
)]
2
public
static
extern
bool
GetArray(
int
ElementNumber, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex
=
0
)]
double
[] BaseAddress);
3
4
private
void
MenuItemFileGetArrayOnClicked(
object
sender, RoutedEventArgs e)
5
{
6
//
Get array data.
7
int
ElementNumber
=
GetArrayElementNumber();
8
double
[] doubleArray
=
new
double
[ElementNumber];
9
GetArray(ElementNumber, doubleArray);
10
11
//
Show the data.
12
mainGrid.Children.Clear();
13
ListBox listBox
=
new
ListBox();
14
foreach
(
double
number
in
doubleArray)
15
{
16
listBox.Items.Add(number);
17
}
18
mainGrid.Children.Add(listBox);
19
}
20
有了这三个功能,通常来讲C++代码复用到C#平台上就是比较简单的事情了。blog