C#/Haskell/F#/JS/C++/...程序员的C++/CLI简明介绍

7

我正在尝试与操作系统以及诸如活动目录和Ocropus之类的东西进行集成。

我掌握了许多编程语言,包括标题中列出的语言。 我正在努力学习C++/CLI的工作原理,但是无法从我所做的搜索中找到简明、准确的描述。 所以我在这里问。

您能告诉我C++/CLI的缺陷和特点吗? 假设我已经掌握了所有的C#,然后再开始。 我不是C++的专家,因此我的一些问题的答案可能是“就像C ++”,但可以说我是在C#方面。 我想知道以下内容:

  • 将C ++指针转换为CLI指针,
  • C# / C ++传递值/双重间接指针/ CLI指针是否有任何区别,以及推荐使用哪种方式。
  • gcnew、__gc、__nogc与
    • 多态
    • 结构体
    • 内部类
    • 接口
  • “fixed”关键字;是否存在?
  • 是否可以使用C++/CLI编译加载到内核中的DLL? 作为设备驱动程序加载? 被内核调用? 这到底意味着什么(即如何将某些内容加载到内核中; 如何知道它是否存在?)
  • L"my string"与"my string"? wchar_t? 有多少种字符类型?
  • 在代码中,我们可以将chars视为uint32s吗? 或者应该将它们视为什么以保证语言无关性?
  • C#中不建议使用终结器(~ClassName() {}),因为不能保证它们会以确定性的方式运行,但由于在C++中我必须使用“delete”或使用副本构造函数以堆栈分配内存,因此在C# / C++交互之间推荐什么?
  • 在C++/CLI中使用反射时需要注意什么?
  • C++/CLI与IDisposable模式以及SafeHandle、SafeHandleZeroOrMinusOneIsInvalid的兼容性如何?
  • 在执行DMA操作时,异步异常是什么?
  • 在使用C++与CLI集成时,是否会对自己施加限制,而不仅仅是使用纯C++?
  • C++中的属性是否类似于C#中的属性?
  • 现在可以通过模板使用完整的元编程模式,并且仍然像普通的C++一样进行编译吗?
  • 您是否尝试过使用boost编写C++/CLI?
  • 接口boost库与C++/CLI的最佳方法是什么? 您能否举一个将lambda表达式传递给iterator / foldr函数的示例?
  • 异常处理的首选方式是什么? C++/CLI现在是否可以捕获托管异常?
  • C++/CLI的动态IL生成效果如何?
  • 它是否在Mono上运行?
  • 还有其他需要了解的事情吗?

注意: 我真正询问的是C++/CLI的特殊之处,以及它的陷阱。


1
我本来打算至少回答一下,给出一些明显的链接,比如Herb Sutter的理由,但我并不确定我看到的任何东西真正回答了你的问题。我想看到一些能够回答问题的东西。 - user180247
3
+close: 范围过于宽泛。如果每个人都能像“在一个帖子中,给我提供一个从编译器到实现再到运行时的整个C++语言的综合描述”的问题一样提问,那就好了。 翻译:该问题范围过于广泛。如果每个人都能像“请在一篇文章中全面描述从编译器到实现再到运行时的整个C++语言”这样提问,那将会很好。请关闭该问题。 - Juliet
1
不同了,我不是要求所有东西,只是从一个非常了解周围CLR的人的角度来看,想要得到全面的信息。你的理由有问题,这是一个什么是太宽泛的问题,也是一个很滑的坡。如果你愿意,随便修改一下这个问题。 - Henrik
2个回答

5
首先,你混淆了已废弃的“托管 C++ 扩展”,它有 __gc 和 __nogc 关键字,与新的、当前支持的 C++/CLI 语言不同,在这个语言中,指针(原生指针)和句柄(托管对象,实际上是指向 .NET 对象所在垃圾回收内存的指针)之间终于提供了适当的区分,但你不应该将句柄视为指针,因为它们会被垃圾回收器自动调整。这两种指针类型完全不同,只有内置类型与两种都兼容,然后你只需将它们装箱以获取句柄。你永远不能有一个指向托管堆之外的句柄,而且你只能在 pin_ptr 生命周期(仅限局部作用域)内获得指向托管堆的原生指针。托管类可以持有指向原生内存的指针,就像 C# 可以具有 IntPtr 成员一样。使用 gcroot 模板类型可以让原生类型持有对托管对象的句柄,它包装了 System::GCHandle。
Microsoft 的 C++/CLI 编译器可生成纯 MSIL 或混合的 MSIL 和原生代码,这取决于你是否使用 /clr 或 /clr:pure 或 /clr:safe(后者限制 /clr:pure 只产生可验证的 MSIL)。你其他大多数问题的答案取决于它处于哪种模式下。例如,任何它生成的 MSIL 都可以在 Mono 上运行,但混合的原生代码和 MSIL 则不能,因为它依赖于 Microsoft .NET 运行时的内部。
任何限制只适用于使用 C++/CLI 创建的托管类型(如 ref class、enum class)。即使编译为纯 MSIL 的原生类型也具有 C++ 语言的完全灵活性,包括多重继承、模板等。
C++/CLI 在本机和托管代码中都捕获托管异常类型(/clr 强制 /EHa 编译器选项)。
C++/CLI 提供了堆栈语义语法(声明一个类型不包括 ^ 后缀的变量)。无论是本地变量还是托管类型的成员变量,这都是可能的。对于所有实现 IDisposable::Dispose 的类型,编译器将自动在所有常规位置(如 C# 中的 using 块)为其生成调用,并自动生成在托管类型中调用 Dispose 的 IDisposable 实现。
尚不支持 Lambda,因为在 Visual Studio 的下一个版本(2010)中,将使用即将发布的 C++ 标准定义的语法添加它们。
无论你使用什么编译器,都不能在内核模式下运行托管代码,C++/CLI 在这个领域没有改变任何事情。
你的问题过多,不适合一次性回答。如果你确实希望我逐一回答每个问题,那么这将是一系列博客文章,并且我将在这里留下一个链接。

嗯,我不知道他是否仍然感兴趣,或者你是否仍然渴望回答所有这些问题,但如果你能代表我发布帖子,我将非常感激。 - marcelo-ferraz

5
将C++指针转换为CLI指针
CLI类型不一定是指针。在C++/CLI中使用句柄 (^)。
来自C#/C++的传递值/双重间接指针/CLI指针是否有差异,以及什么是“推荐”的方式。
如果需要更好的与C#互操作性,请避免使用指针。在C++/CLI中使用所有关于指针的内容,并仅公开托管类型,以便C#应用程序可以轻松使用它。
“fixed”关键字是否存在? pin_ptr<>有相同的功能。
由于C#中没有保证终结器(~ClassName() {})将以确定性方式运行,因此不鼓励在C#中使用它们。但是,由于在C++中我必须使用“delete”或使用副本c'tors以堆栈分配内存,因此在C#/C++交互方面有哪些建议?
C++/CLI支持确定性资源管理。当您编写析构函数时,编译器将在类上实现IDisposable接口,并将析构函数转换为Dispose()方法。delete将调用此Dispose()以进行资源释放。由于此原因,您在从C#中使用它时不会遇到问题。您可以在C#中使用using语句封装使用,以确保调用Dispose()。
C++中的属性类似于C#中的属性吗?
是的,它们非常相似。
我可以使用C++中可用的完整元编程模式来编写模板,而仍然像普通C++一样进行编译吗?
可以。C++/CLI支持ref类上的模板。您可以像在标准C++中一样使用元编程技术。但是这些不会在C#中可移植。
您尝试过使用boost编写C++/CLI吗?
C++/CLI可以访问整个.NET框架。我认为boost在这里没有太大帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接