我正在研究开发一种应用程序,它将以每秒约2000行(帧)的速度处理来自线扫描相机的数据.对于这个实时应用程序,我觉得C/C++是要走的路.(这是我的感觉,其他人会同意托管代码不适合这项任务.)
不过,我已经做了非常少的MFC或任何其他的C++图形用户界面.不过,我真的很想做C#GUI.
所以我很自然地用C/C++编写数据密集型代码,用C#编写GUI.GUI将用于设置/校准/在线监控(并可能通过UDP输出数据,因为它在C#中更容易.
首先,我想看看是否有人同意这将是要走的路.根据我的编程经验(擅长低级C算法和高级C#GUI设计),感觉恰到好处.
其次,我不确定正确的方法.我只是在VS2005中汇总了一个解决方案,它从C#应用程序中调用了一些(extern"C")DLL函数.为了确保我能做到这一点,我写了DLL中的一些全局变量,并从中读取:
test.h
int globaldata; extern "C" __declspec(dllexport) void set(int); extern "C" __declspec(dllexport) int get();
TEST.CPP
extern int data=0; __declspec(dllexport) void set(int num) { data = num; } __declspec(dllexport) int get() { return data; }
test.cs中
[DllImport("test")] private static extern void set(int num); [DllImport("test")] private static extern int get();
调用get()
并set()
正常工作(get()
返回我传递给的数字set()
).
现在,我知道您也可以导出C++类,但它是否必须进行管理?这是如何运作的?我是以正确的方式来做这件事的吗?
感谢你的帮助!
*** EDIT ***
首先,感谢您迄今为止的精彩答案!我总是对Stack Overflow印象深刻......
我想我应该更多地关注一件事,不一定是原始速度(这可以是原型和基准测试).让我更关心的一件事是垃圾收集器的非确定性行为.这个应用程序将不会在执行垃圾收集宽容500ms的延迟.
我只是编写代码并在纯C#中尝试这个,但如果我提前知道GC和任何其他非确定性的.NET行为(?)会导致问题,我认为我的时间会更好地用于编码C/C++并找出最好的C#接口.
没有理由不能完全用C#编写高性能代码.
性能(C#编程指南)
Rico Mariani的表演博客(一个很好的资源)
调整.NET应用程序性能
关于相同/类似主题的问题:
C++性能与Java/C#
c ++比c#快多少?
其他文章:
Microbenchmarking C++,C#和Java
利用C#的特点为您的科学计算项目提供动力
使用Visual Studio Profiler查找应用程序瓶颈
揭穿C#与C++性能
在我看来,你的解决方案是合理的:
尽管C#速度很快,但它永远无法与编写良好的非托管C/C++竞争,我自己制作了高性能的应用程序,证明了这一点超出了人们在发布这些语句时总是发布的小例子
MFC或ATL UI编程既繁琐又慢,C#是走到这里的方式,我永远不会再做MFC/ATL UI编程,除非被迫
你的解决方案,如果你还没有想到它,被称为"混合模式",这基本上意味着你在同一个项目中结合托管(C#)和非托管(C/C++)代码,它通常是一点点让VS项目正常运行的麻烦(LNK2020错误......)......但是当你找到合适的设置时它应该可以正常工作.
唯一不好的是,混合模式程序集必须在完全信任中运行,如果可以,那么我想你知道该怎么做.
您可能想要关注的另一件事是一个名为SWIG的开源项目.SWIG接受你的C/C++代码并用它创建一个.NET程序集,我在我的TM ++开源项目中自己使用它.有关SWIG http://www.swig.org/的更多信息,请参见此处.
对于实时应用:我推荐使用C++,根据使用的框架,你将更灵活地进行内存管理,更快,甚至是多平台...!
关于框架和GUI,我建议你看看Qt.Qt是一个很好的C++软件开发框架.
我想这是你问题的解决方案!
你需要做的第一件事是测试你的假设.你的性能限制是什么?您期望托管应用程序的硬件类型是什么?在C#中编写一个小程序来处理核心问题并测量其运行速度.
只有掌握了事实,才能决定是否在托管解决方案上使用C/C++.
与其他评论过的人一起,我怀疑C#/托管解决方案会做得很好,特别是如果你使用.NET Parallel Extensions.
如果你最终进入C/C++路由,那么有两个选项可以互操作,即pInvoke和COM互操作.我不相信有一种直接从.NET访问非托管C++类的简洁方法; 为此,您必须考虑实现托管/非托管C++程序集.
我的公司做的事情非常相似,尽管使用的是CCD摄像机而不是线扫描摄像机。我们将C#用于GUI,网络通信,高级“管道”和C ++ / CLI用于低级算法。效果很好。您将永远无法在Windows上编写具有保证的最大响应时间的真正的实时系统,但是根据我的经验,GC在这里将是最少的问题。一方面,GC仅在分配内存时运行;C / C ++中的malloc / new也是如此,它们也需要时间(请考虑内存碎片)。从我们完成的测量来看,一个完整的GC需要10-50ms的时间,并且在此期间不必停止其他线程(我认为除非它们尝试分配托管内存),这对我们来说是可以的。但是我不确定这些数字是否可以推广到任何类型的应用程序,
如果您担心GUI可能会突破实时限制,则可以考虑将实际的图像处理置于单独的进程中,并使用管道/套接字与GUI进行通信。或者至少在设计系统时牢记该选项,因此,如果您确实遇到无法预料的性能问题,则将其作为最坏情况的选择。
您的第二个问题是,对于实际算法,应使用C ++还是C#。就个人而言,当我编写复杂的图像处理算法时,我会在C ++中感到更加舒适。我认为该语言更适合该任务,并且C / C ++的数字处理库比C#的要多得多。但这可能是个人喜好问题。从性能的角度来看,C ++的优势在于C ++内联比.NET JIT内联更好(即,它可以内联更多的小函数调用)。
如果您选择使用C ++,我建议您使用C ++ / CLI:这样,您可以编写编译成托管代码的C ++类。C ++优化器将优化它们,.NET JIT仅完成对本机代码的最后编译步骤。最大的优点是您可以直接从C ++ / CLI访问.NET类,并且可以轻松地在C ++ / CLI中创建可从C#访问的托管类。您无需在围栏的两侧都编写包装器代码。(C ++ / CLI有点笨拙,因为它包含用于托管和非托管编程的语言构造,但是如果您已经熟悉非托管C ++和C#,那么理解它可能不会有任何问题。)