为 C#/Haskell/F#/JS/C++/... 程序员简要介绍 C++/CLI
我正在尝试编写与操作系统以及活动目录和 Ocropus 等的集成。
我知道很多编程语言,包括标题中列出的那些。我正在尝试确切地了解 C++/CLI 的工作原理,但从我所做的搜索中无法在网上找到简洁、准确和准确的描述。所以我在这里问一下。
您能告诉我 C++/CLI 的陷阱和特点吗?假设我了解所有 C# 并从那里开始。我不是 C++ 方面的专家,所以我的一些问题的答案可能是“就像 C++ 一样”,但可以说我是 C# 的。我想知道以下内容:
- 将 C++ 指针转换为 CLI 指针、
- C#/C++ 中按值/双重间接指针/CLI 指针传递的任何差异以及“推荐”内容。
- gcnew、__gc、__nogc 如何使用
- 多态性
- 结构
- 内部类
- 接口
- “fixed”关键字;那存在吗?
- 可以使用 C++/CLI 编译加载到内核中的 DLL 吗?作为设备驱动程序加载?由内核调用?无论如何,这意味着什么(即将某些东西准确地加载到内核中;我如何知道它是否是?)?
- L“我的字符串”与“我的字符串”? wchar_t?字符有多少种类型?
- 我们将 char 视为 uint32 是否安全,或者应该如何对待它们以保证代码中的语言无关性?
- 在 C# 中不鼓励使用终结器 (~ClassName() {}),因为没有保证它们将确定性地运行,但由于在 C++ 中我必须使用“删除”或使用复制器来堆栈分配内存,所以什么是C#/C++ 交互之间的建议?
- 在 C++/CLI 中使用反射有哪些陷阱?
- C++/CLI 与 IDisposable 模式以及 SafeHandle、SafeHandleZeroOrMinusOneIsInvalid 的配合效果如何?
- 我已经简要阅读了有关执行 DMA 操作时的异步异常的信息,这些异常是什么?
- 当使用 C++ 与 CLI 集成而不是仅仅使用普通的 C++ 时,您是否对自己施加了限制?
- C++ 中的属性与 C# 中的属性类似吗?
- 我现在可以通过模板使用 C++ 中可用的完整元编程模式,并且仍然像普通 C++ 一样进行编译吗?
- 您尝试过使用 boost 编写 C++/CLI 吗?
- 将 boost 库与 C++/CLI 连接的最佳方式是什么?您能给我一个将 lambda 表达式传递给迭代器/foldr 函数的示例吗?
- 异常处理的首选方式是什么? C++/CLI 现在可以捕获托管异常吗?
- 动态 IL 生成与 C++/CLI 的配合效果如何?
- 它在 Mono 上运行吗?
- 还有其他我应该知道的事情吗?
注意:我真正想问的是 C++/CLI 的特殊性,即它的陷门。
I'm trying to write integrations with the operating system and with things like active directory and Ocropus.
I know a bunch of programming languages, including those listed in the title. I'm trying to learn exactly how C++/CLI works, but can't find succinct, exact and accurate descriptions online from the searching that I have done. So I ask here.
Could you tell me the pitfalls and features of C++/CLI? Assume I know all of C# and start from there. I'm not an expert in C++, so some of my questions' answers might be "just like C++", but could say that I am at C#. I would like to know things like:
- Converting C++ pointers to CLI pointers,
- Any differences in passing by value/doubly indirect pointers/CLI pointers from C#/C++ and what is 'recommended'.
- How do gcnew, __gc, __nogc work with
- Polymorphism
- Structs
- Inner classes
- Interfaces
- The "fixed" keyword; does that exist?
- Compiling DLLs loaded into the kernel with C++/CLI possible? Loaded as device drivers? Invoked by the kernel? What does this mean anyway (i.e. to load something into the kernel exactly; how do I know if it is?)?
- L"my string" versus "my string"? wchar_t? How many types of chars are there?
- Are we safe in treating chars as uint32s or what should one treat them as to guarantee language indifference in code?
- Finalizers (~ClassName() {}) are discouraged in C# because there are no garantuees they will run deterministically, but since in C++ I have to use "delete" or use copy-c'tors as to stack allocate memory, what are the recommendations between C#/C++ interactions?
- What are the pitfalls when using reflection in C++/CLI?
- How well does C++/CLI work with the IDisposable pattern and with SafeHandle, SafeHandleZeroOrMinusOneIsInvalid?
- I've read briefly about asynchronous exceptions when doing DMA-operations, what are these?
- Are there limitations you impose upon yourself when using C++ with CLI integration rather than just doing plain C++?
- Attributes in C++ similar to Attributes in C#?
- Can I use the full meta-programming patterns available in C++ through templates now and still have it compile like ordinary C++?
- Have you tried writing C++/CLI with boost?
- What are the optimal ways of interfacing the boost library with C++/CLI; can you give me an example of passing a lambda expression to an iterator/foldr function?
- What is the preferred way of exception handling? Can C++/CLI catch managed exceptions now?
- How well does dynamic IL generation work with C++/CLI?
- Does it run on Mono?
- Any other things I ought to know about?
Note: I'm really asking about the peculiarities of C++/CLI, its trapdoors.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
CLI 类型不必是指针。在 C++/CLI 中使用句柄 (^)。
如果需要与 C# 更好的互操作性,请避免使用指针。使用 C++/CLI 中所有与指针相关的内容,并仅公开托管类型,以便 C# 应用程序可以轻松使用它。
pin_ptr
是等效的。C++/CLI 支持确定性资源管理。当您编写析构函数时,编译器将在类上实现
IDisposable
接口,并将析构函数转换为Dispose()
方法。 delete 将调用此Dispose()
来取消资源分配。因此,从 C# 使用它不会出现任何问题。您可以将用法包装在 C# 中的using
语句中,这将确保调用Dispose
。是的,它们很相似。
是的。 C++/CLI 支持引用类上的模板。您可以像在标准 C++ 中一样使用元编程技术。但这些不能移植到 C#。
C++/CLI 可以访问整个 .NET 框架。我认为 boost 在这里没有多大帮助。
CLI types don't have to be pointers. In C++/CLI handle (^) is used.
If you need better interoperability with C#, avoid using pointers. Use all the pointer related stuff in C++/CLI and expose only managed types so that C# applications can use it easily.
pin_ptr<>
is the equivalent.C++/CLI supports deterministic resource management. When you write a destructor, compiler will implement
IDisposable
interface on the class and convert destructor intoDispose()
method. delete will call thisDispose()
to do the resource de-allocation. Because of this, you don't have issues in using it from C#. You can wrap the usage inusing
statement in C# which will ensure call onDispose
.Yes they are similar.
Yes. C++/CLI supports templates on ref classes. You can use metaprogramming techniques like you do in standard C++. But these won't be portable to C#.
C++/CLI has access to the whole .NET framework. I don't think boost helps much here.
首先,您会将现已不存在的“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 类、枚举类)。本机类型即使编译为纯 MSIL,也具有 C++ 语言的全部灵活性,包括多重继承、模板等。C
++/CLI 捕获本机和托管代码中的托管异常类型(/clr 强制 /EHa 编译器选项)。
C++/CLI 提供了堆栈语义语法(声明类型不包含 ^ 后缀含义句柄的变量)。这对于局部变量和托管类型的成员都是可能的。编译器将自动为在所有常用位置实现 IDisposable::Dispose 的类型生成对 IDisposable::Dispose 的调用(如用于局部变量的 C# using 块,自动在托管类型中创建 IDisposable 实现,对所有成员调用 Dispose)。
Lambda 尚不可用,因为在下一版本的 Visual Studio (2010) 中,将使用即将推出的 C++ 标准定义的语法添加它们。
无论使用什么编译器,都无法在内核模式下运行托管代码,C++/CLI 在这方面没有任何改变。
对于一个问题来说,你的观点确实太多了。如果您真的希望我详细介绍每一点,我会的,但这将是一系列博客文章,我将在此处留下一个链接。
To start with, you're confusing the now-defunct "Managed extensions for C++" which had __gc and __nogc keyword, with the new and currently supported C++/CLI language, which finally provides a proper distinction between pointers (native) and handles (managed objects, they're actually implemented as pointers into garbage collected memory where .NET objects live, but you shouldn't think of them as pointers because they get adjusted automatically by the garbage collector). The two types of pointers are completely distinct, only builtin types are compatible with both and then you just box them to get a handle. You can never have a handle pointing outside the managed heap and you can only get a native pointer into the managed heap for the duration of a pin_ptr lifetime (local scope only). A managed class can hold a pointer to native memory, just like C# can have IntPtr members. Native types can hold handles to managed objects using the gcroot templated type, which wraps System::GCHandle.
The Microsoft C++/CLI compiler is capable of generating either pure MSIL or a mixture of MSIL and native code, depending on whether you use /clr or /clr:pure or /clr:safe (the last restricts /clr:pure to produce only verifiable MSIL). The answers to most of your other questions depend on which of these modes it is in. For example, any MSIL it produces will run on Mono, but mixed native and MSIL won't, because it relies on internals of the Microsoft .NET runtime.
Any limitations apply only to managed types (e.g. ref class, enum class) created with C++/CLI. Native types, even when compiled to pure MSIL, have the full flexibility of the C++ language including multiple inheritance, templates, etc.
C++/CLI catches managed exception types in both native and managed code (/clr forces the /EHa compiler option).
C++/CLI provides a stack semantics syntax (declare a variable whose type doesn't include the ^ suffix meaning handle). This is possible for both local variables and members of managed types. The compiler will automatically produce calls to IDisposable::Dispose for types which implement it in all the usual places (like a C# using block for local variables, automatically create an IDisposable implementation in managed types which calls Dispose on all members).
Lambdas aren't available yet, because in the next version of Visual Studio (2010) they will be added using the syntax defined by the upcoming C++ standard.
You can't run managed code in kernel mode regardless of what compiler you use, C++/CLI changes nothing in this area.
You really have way too many points here for a single question. If you really want me to go through every point I will, but it's going to be a series of blog entries and I'll just leave a link here.