托管c++库,它是如何工作的

本文关键字:工作 何工作 c++ 托管 | 更新日期: 2023-09-27 18:16:03

我发现有一堆项目(SharpDX等)正在编译中,允许CLR"管理"本地代码,然后直接从c#调用该本地代码(c++函数)。

我正在努力弄清楚这是如何工作的,如果你们中有人知道的话,那就太好了。

到目前为止我所看到的是,我可以将c#项目中的引用添加到"CLR兼容"的c++库中,就像任何其他c#库一样(不需要反射),添加它像:"使用mycplibrary",然后只需调用其上可用的任何方法。

当我去看看我刚刚添加的参考中有什么函数可用时,似乎我可以从c#访问任何在c++库的头文件(.h)上声明为PUBLIC的内容,因为它们会被编译器自动转换为c#代码。

所以实际上是这样的:

我在c++库的头文件(.h)中声明了公共方法/变量。我编译它们,检查CLR管理是否在库的属性选项卡中可用。(我使用的是Visual Studio 2012)编译器会为每个带有公共方法/属性的头文件(.h)生成c#类。

但是我不明白的是,当我调用让我们说,givennumber()函数从" mycplibrary "..该功能的实现在哪里进行?

CLR是否自动与c++本地代码进行内部通信,或者实际发生了什么?

托管c++库,它是如何工作的

我不太清楚你看到的是什么。但是很有可能你看到了一个错误的副作用。c++/CLI编译器能够将任何c++ 03兼容的本地c++代码编译成IL。IL和jitter都足够灵活来支持这一点。就像c#编译器生成的IL一样,这种IL将在运行时被翻译成机器码,并以完全相同的方式进行优化。

但是不使成为托管代码。这段代码创建的任何对象仍然是在非托管内存中分配的本机对象,就像本机c++编译器一样。垃圾收集器对它们是完全不知情的。

的错误是允许代码被翻译成IL。你错过了c++代码生成器可以在编译时花费的额外时间来找到最佳优化的机器码。抖动也可以优化,但它不能做得很好,必须在时间限制下运行。当然,你还需要在运行时承担编译开销。

本机结构和类将在程序集元数据中可见。但是它们只是不透明的值类型,c#程序无法访问它们的成员。你不能从c#中直接调用这样一个原生类的方法。为了可用,c++/CLI程序必须使用ref上下文关键字声明类型。像ref class,完全等同于c#类。

因此,将本机代码编译为机器代码是很重要的,就像普通的c++编译器一样。您可以通过编译一个.cpp源文件而不使用/clr来实现。或者用#pragma unmanaged和#pragma managed包装这些代码,在机器码和IL生成之间来回切换编译器。从c++/CLI中获得的附加价值是,ref类中的方法可以直接使用本机代码,而不必像在c#中那样经历像pinvoke这样的麻烦。并且使用本地c++类,这在c#中是完全做不到的。

当您在c++中启用CLR时,编译器将c++代码编译为IL而不是本地代码。在这种情况下,c++,被称为 c++/CLI被增强了各种特性,以允许它使用垃圾收集器,可以很好地控制是否固定垃圾收集的内存以避免它移动,等等。

一般来说,编写c++/CLI是一项专业任务,需要掌握c++和c#的知识(可能会有一些细微的差异和陷阱)。它通常被推荐用于本机代码和托管代码之间的接口,但它也可以用于将整个库集成到。net中。