代码之家  ›  专栏  ›  技术社区  ›  Brett Allen

C++/CLI在C语言中使用的情况或利弊

  •  8
  • Brett Allen  · 技术社区  · 15 年前

    我已经跟不上.NET CLR一段时间了,我选择的语言是C。

    直到最近,我才意识到C++/CLI可以产生能够运行本地和托管代码的“混合模式”可执行文件。

    现在知道了这一点,我的另一位开发人员朋友正在讨论这个属性,并试图确定这个功能何时以及如何有用。

    我把它当作一个给定的本地代码 能力 以牺牲额外的开发时间为代价,比托管代码更高效、更强大。

    在过去,我采用了严格的本地C++代码库,并使用互操作来利用我编写的函数到本机库中。

    我可以看到不需要一个额外的库的好处,但是我很好奇在C++中使用Cy+/CL在SOLY管理的可执行文件上使用的所有优点和缺点,或者使用互操作调用一个纯本地C++库的一个可执行文件。

    (旁注:术语interop/pinvoke是否可以互换,因为i d.on不理解术语之间的区别,只是简单地看到它们使用相同的方式。)

    4 回复  |  直到 15 年前
        1
  •  13
  •   philsquared    15 年前

    用C++/CLI,可以概括地说,创建三种对象:

    1. 托管类型。这些将编译为基本上与等效的c_相同的il。这里没有表演机会。
    2. 本地类型。编译成本机代码,就像使用直C++一样。
    3. 混合模式类型。这些代码编译为托管代码,但也允许您引用本机类型。

    您可能会认为(3)就像用pinvoke代码编写C代码来访问本机内容一样-除了所有pinvoke内容都是为您生成的。

    当然,除了这些以外,还有一些注意事项——但这应该让你知道它是如何有用的。

    换句话说,它真的是一种胶语言。虽然你可以在C++或CLI中编写完全成熟的应用程序,但是将托管和本地部分分开并使用C++/CLI来桥接两个更干净的应用程序比使用PInvoke更为正常。

    另一个常用的用法是用.NET库调用扩展和存在本机C++代码库。

    只需小心,你可以很好地划分你的代码,因为在编译你的纯C++代码到透明的IL时有时会很微妙。

    关于你的旁注:pinvoke是一种特殊的互操作类型。interop也有其他形式,比如com interop。事实上,更准确地说,pinvoke是一组语言特性,使与本机代码的互操作更加容易。

        2
  •  3
  •   Randolpho    15 年前

    过去我已经有效地使用了托管C++(.c++/CLI的.NET 1.1前体)。当您希望在托管代码中使用本机C或C++库时,我发现它是最有效的。您可以进入整个互操作/ pJoCK路由,这使得一些丑陋的C代码和经常出现编组问题,或者您可以编写一个托管C++封装器,这是C++/CLI真正闪耀的地方。

    因为C++/CLI是托管代码,所以可以通过添加对.dll的引用,以正常方式调用它从C(VB.NET)调用。没有马歇尔,没有德林波特,没有那样愚蠢的。只是普通的项目引用。另外,如果您的本机库是这样设计的,那么静态链接库的好处就在于它是一件好事(tm)。

        3
  •  2
  •   Community Dunja Lalic    7 年前

    Phil Nash 真的很重要。这是我不止一次命中的一个,也是我过去使用C++/CLI的主要原因:

    某些应用程序通过在某些位置选中所有DLL来扩展具有特定名称的导出函数。在C++中,没有办法声明一个原生的C风格的导出,但是你可以在C++/CLI中使用。我在C++/CLI中创建了一个“包装器”,它导出方法,处理C结构到托管对象的任何翻译,并将调用传递给用C语言编写的程序集。

        4
  •  1
  •   Sheng Jiang 蒋晟    15 年前

    某些类型对其他语言不可用,例如模板, 装箱值类型的常量和跟踪句柄。

    模板在编译时专门化。泛型在运行时专门化。尽管clr应该缓存泛型专门化以供将来使用(这样每次使用它时都会得到相同的列表),但是每次请求泛型专门化时仍然会有性能问题。

    我知道其他语言抛弃了const属性,但是在C++代码中编译时间检查总比没有好。

    使用int^这样的类型可以访问托管堆目录上的内存,而不必取消绑定。当将装箱值的跟踪句柄传递给需要跟踪句柄的函数(如console::writeline(object^))时,这有助于提高性能。当然,不能避免过早的装箱初始化。在其他语言中,您可以将引用存储在一个对象变量中并传递它以避免取消绑定,但是您会丢失编译时类型检查。