将C ++和C#结合起来是一个好主意还是会造成任何直接问题?
我有一个应用程序,需要一些部分是C ++,有些部分是C#(为了提高效率)。在C#中使用本机C ++ dll的最佳方法是什么?
答案 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 ++库(如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 ++差异以及合并它们的可能性问题的其他信息:
Mono
,但在其他平台上却没有那么好(或根本没有)(Android) ,IOS,其他人。)如果你想在没有操作系统支持的情况下编写嵌入式软件,或者自己编写操作系统,你大多“不能”使用C#。只要你有一个编译器(通常就是这种情况),C ++就完全是跨平台的。将它们组合起来是个好主意吗?
这可能取决于你的项目。 对于Windows上的大型HMI开发,这可能会缩短您的开发时间。但是,其他软件要求可能仅限于使用C ++。
[1]我多次读过解释代码在某种情况下甚至比二进制代码更快,这是由于一个误解: 解释器为了方便实现了几个函数,所以当你调用(例如)sort()时,实际上它调用了这个函数的二进制实现。如果这个函数得到了很好的优化,那么最后的时间可能会更快,但只是因为所有运行都是二进制的,并且与排序所需的所有时间相比,解释的组件是最小的。另一方面,如果您使用两种语言编写完整逻辑,则二进制版本将始终显着更快。原因很简单:解释器是一个二进制文件,除了代码之外还运行所有语言框架。