结合C ++和C#

时间:2010-03-28 12:42:47

标签: c# c++

将C ++和C#结合起来是一个好主意还是会造成任何直接问题?

我有一个应用程序,需要一些部分是C ++,有些部分是C#(为了提高效率)。在C#中使用本机C ++ dll的最佳方法是什么?

3 个答案:

答案 0 :(得分:34)

问题显然是如何将他自己的C ++代码集成到他的C#解决方案中,而不仅仅是使用什么属性来从win32 API调用现有函数。即使答案已经被接受,我认为这是不完整的,并且应该适用以下内容。

是的,在任务可以运行得更快,使用更少的资源以及在某些情况下访问.net框架中不可用的方法的情况下,这是常见的做法。

如果您的目标是提高效率,则需要编写本机非托管C ++库,您将在visual studio中创建一个新的非托管C ++项目(编译为dll库)并引用此库来自你的C#项目。

在您的情况下,您似乎可能正在编写非托管C ++库,以下内容适用。

对于您询问的任何直接问题,它会影响部署和混淆。

  • 部署:请记住,您构建的C#DLL将在任何上运行 CPU,32和64bit,但这个新的 本机和非托管C ++库将 迫使你的程序要么 32或64具体。

    这是您要配置的内容 在Visual Studio配置管理器中,和 将在编译时处理 时间,你会为C#选择AnyCPU 程序集和新的非托管C ++库,它将在它自己的项目中,你将拥有 从win32或x64中选择。

    所以你现在将有2个设置,它是 建议的最佳做法 单独的设置,一个用于32和 另一个为64.或者自32bit 支持率正在迅速下降,你 可能只关注64位。

    此外,您的库最终可能会引用Visual Studio提供的VC ++ redistibutable,您可能必须将其包含在部署中,尽管它的某些版本包含在许多操作系统中,但我发现它很少与我编译的相同。并且最好将它与您的应用程序一起部署以确保。如果缺少此包,则目标计算机将在eventviewer->应用程序日志中具有SideBySide异常。

    要捕获并处理从非托管代码抛出的异常,唯一有效的catch是空的,catch()之后的括号中没有异常类型的catch。因此,您可以将对此非托管代码的调用包装起来,以处理从非托管代码中抛出的所有非托管异常,如果您放置类似catch(异常)的.net类型,它将跳过它。在托管代码中捕获非托管异常的唯一方法是采用这种格式。


    try
    {
       //call unmanaged code
    }
    catch
    {
       //handle unmanaged exception
    }

  • 混淆:从C#完成的任何方法调用正在调用 现在将排除非托管代码 从自动重命名。另一方面, 如果您的非托管C ++库需要 从您的托管中调用方法 组件,那些将是必需的 排除重命名,手动,以便 C ++库调用可见 它们。

如果您需要的只是调用知名的C ++库(如Windows),则不需要创建新的非托管C ++项目,只需使用前一个答案中建议的[DllImport()]属性。在这种情况下,您可以查看此参考http://www.pinvoke.net/

答案 1 :(得分:31)

是的,使用C#和C ++为您的产品是非常普遍和一个好主意。

有时您可以使用托管C ++,在这种情况下,您可以像使用任何其他.NET模块一样使用托管C ++模块。

通常,您可以在C#中执行所有操作。对于您需要在C ++中执行的部分,您通常会创建一个C ++ DLL,然后从C#调用该DLL。参数编组会自动为您完成。

以下是将DLL内部的C函数导入C#:

的示例
[DllImport("user32", CharSet=CharSet.Auto, SetLastError=true)]
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);

答案 2 :(得分:-5)

有关C#与C ++差异以及合并它们的可能性问题的其他信息:

  • C#是一种解释,就像Java一样。 C ++被编译为本机二进制文件。这带来了几个差异,在以下几点进一步解释。即使使用JIT,也需要翻译的初始阶段。
  • 平台兼容性:C#,经过解释和Microsoft产品,它可以在Windows上正常运行,这要归功于一个很棒的项目Mono,但在其他平台上却没有那么好(或根本没有)(Android) ,IOS,其他人。)如果你想在没有操作系统支持的情况下编写嵌入式软件,或者自己编写操作系统,你大多“不能”使用C#。只要你有一个编译器(通常就是这种情况),C ++就完全是跨平台的。
  • 解释代码通常比二进制代码慢一个数量级[1]。这是在C#中链接C ++的一个原因。
  • 二进制代码与中间代码:中间代码适用于特定体系结构上可用的任何解释器,C ++需要重新编译每个体系结构。
  • 学习曲线:为了结合两种语言,开发人员需要学习多种语言,这会增加学习时间。找到两种语言的专家也很难。
  • IDE:对于C ++,任何文本编辑器都足够了,对于C#,您将主要需要特定的IDE。
  • 实时:用C#设想实时条件似乎很难。
  • 使用C#代码(关键软件)无法获得某些质量认证。

将它们组合起来是个好主意吗?

这可能取决于你的项目。 对于Windows上的大型HMI开发,这可能会缩短您的开发时间。但是,其他软件要求可能仅限于使用C ++。

[1]我多次读过解释代码在某种情况下甚至比二进制代码更快,这是由于一个误解: 解释器为了方便实现了几个函数,所以当你调用(例如)sort()时,实际上它调用了这个函数的二进制实现。如果这个函数得到了很好的优化,那么最后的时间可能会更快,但只是因为所有运行都是二进制的,并且与排序所需的所有时间相比,解释的组件是最小的。另一方面,如果您使用两种语言编写完整逻辑,则二进制版本将始终显着更快。原因很简单:解释器是一个二进制文件,除了代码之外还运行所有语言框架。