关于混合C#和C++的编程方式,本人之前写过一篇博客(参见 混合语言编程:C#使用原生的Directx和OpenGL ),在之前的博客中,介绍了在C#的Winform和WPF下使用原生的Direct和OpenGL进行绘图,主要使用的方式是声明一个函数为导出函数,然后就可以在C#中使用这个函数。
之前的方式使C#调用C/C++成为可能,但是存在很多缺点,主要表现在以下几个方面:
extern "C" _declspec(dllexport)
的声明方式只能定义C函数,无法直接使用C++的类,功能不够强大。 前段时间开发的一个应用程序中需要控制两个数采卡(SP Divece 的ADQ和SDR),官方提供了C和C++的驱动,可以使用C/C++对数采卡进行控制。我最开始还是使用了之前声明导出函数的方式进行开发,用C语言实现,但是随着功能的复杂和代码的增加,上面一系列问题越来越严重。
在奋斗解决各种Bug的时候突然在一次搜索时找到了 公共语言运行时编译 。所谓公共语言运行时编译,就是允许应用程序和组件使用公共语言运行时 (CLR) 中的功能。找到MSDN上的相关文档:
有了公共语言运行时编译,在C#程序集中就可以引用C++开发的DLL,并且使用C++的类就和使用使用C#类是一样的,还可以直接断点调试,以上问题全部解决。
很快,我就把之前用C写的代码改写成了C++的代码,启用CLR,并删掉了C#中重复的代码。
使用C++开发就会经常使用到指针,但C#没有指针(一般情况,其实C#是有指针的,只不过默认被关闭了)。在C#中要传递一个指针至少有两种方式:
使用 stackalloc
在栈上分配内存块,这类似于C的 malloc
和C++的 new
(当然还是有区别的),详细信息可参考 stackalloc(C# 参考) 。
使用 fixed语句
固定变量的指针,C#中之所以不让用指针,就是因为由于垃圾回收机制会导致变量重定位,变量重定位后,之前的指针也就不再指向这个变量了,所以C#在这种情况下是要禁止使用指针。而 fixed 语句
禁止垃圾回收器重定位可移动的变量,并在执行该语句期间“固定”此变量。固定变量的位置后就可以使用指针了,详细信息可参考 fixed 语句(C# 参考) 。
需要提醒的是,这两种方式都需要在不安全的上下文中使用,关于不安全上下文,可参考 unsafe(C# 参考) 。
本文主要记录我在做项目中发现的问题、解决问题所使用到相关的技术,有效地解决了C#调用C++的问题。当然,其中还有很多细节并没有深入研究,可能会存在更好的方式。