博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#和C++混合编程
阅读量:6476 次
发布时间:2019-06-23

本文共 3179 字,大约阅读时间需要 10 分钟。

 

由于历史原因,很多时候我们的代码并不完全是使用.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类自动处理)

这样的调用还支持调试。打开C#工程的Properties,在Debug选项卡中勾选Enable unmanaged code debugging即可启用C++代码调试。这样在调试模式下,调用这个函数时可以继续按F11跟进函数内部进行调试。

传递GDI对象

一些复杂的Windows对象可以通过句柄来传送。比如下面的代码就将一个GDI+ Bitmap对象转换成GDI句柄进行传送。

C++代码(GDI+的声明,引用等等省略):

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++代码:

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#平台上就是比较简单的事情了。

转载地址:http://ocmko.baihongyu.com/

你可能感兴趣的文章
扫描----整理
查看>>
IOS 手机震动
查看>>
智能指针的实现
查看>>
《The Missing Manual Javascript 》 - 书摘精要
查看>>
C#和Modbus通信工程
查看>>
winedit 改字体大小
查看>>
如何成为“10倍效率的开发者”
查看>>
在JAVA中如何判断按下两个键
查看>>
无法安装程序包“MIcrosoft.Owin.Security 2.0.2”。您正在尝试将此程序包安装到某个将“.NETFramework,Version=v4.0”作为目标的项目中。...
查看>>
spark使用scala读取Avro数据(转)
查看>>
中文词频统计
查看>>
「苦练基本功」超级大佬推荐工程师必看的书感悟
查看>>
折腾笔记之wordpress安装出现错误---【wordpress点击文章找不到网页的解决办法】...
查看>>
387. 最小差
查看>>
LCS问题
查看>>
使用ReaderWriterLock类实现多用户读/单用户写同步
查看>>
第4次作业类测试代码+105032014158+余超勇
查看>>
有关于虚拟DOM
查看>>
codves 4927 线段树练习5
查看>>
幻方(zjut1005) 与 反幻方(hdu 3927)
查看>>