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

时间:2013-05-30 20:18:22

标签: c# c++ visual-c++

我发现有很多项目(SharpDX等)正在编译,以允许CLR“管理”本机代码,然后直接调用该本机代码(c ++函数),例如:c#。

我正在试图弄清楚它是如何工作的......如果你们中的任何人都知道那就太好了。

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

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

所以实际发生的事情是:

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

但是我不明白的是,当我调用时,如何调用“myCppLibrary”中的giveNumber()函数..执行该函数的执行情况是什么?

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

2 个答案:

答案 0 :(得分:3)

不太确定我完全理解你所看到的。但是你很有可能看到错误的副作用。 C ++ / CLI编译器能够将任何与C ++ 03兼容的本机C ++代码编译到IL中。 IL和抖动都足够灵活,可以支持这一点。就像C#编译器生成的IL一样,这种IL将在运行时转换为机器代码,并以完全相同的方式进行优化。

然而使其成为托管代码。此代码创建的任何对象仍然是在非托管内存中分配的本机对象,就像本机C ++编译器一样。垃圾收集器完全没有注意到它们。

然后错误是允许将代码转换为IL。您错过了C ++代码生成器在编译时可以花费额外时间来查找最佳优化机器代码的时间。抖动也会优化,但它不能做得很好,不得不在时间限制下运行。当然,你会在运行时接受jitting开销。

本机结构和类将在程序集元数据中可见。但它们只是不透明的值类型,而它们的成员无法访问C#程序。您无法直接从C#调用此类本机类的方法。要使用,C ++ / CLI程序必须使用 ref 上下文关键字声明类型。与 ref class 类似,与C#类完全等效。

因此,将本机代码编译为机器代码非常重要,就像常规C ++编译器一样。您可以通过编译没有/ clr的.cpp源文件来实现此目的。或者通过使用#pragma unmanaged和#pragma managed包装这些代码,在机器代码和IL生成之间来回切换编译器。从C ++ / CLI获得的值是,ref类中的方法可以直接使用本机代码,而不必像在pinvoke中那样在C#中遇到麻烦。并使用本机C ++类,这是C#无法完成的。

答案 1 :(得分:2)

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

编写C ++ / CLI通常是一项专业任务,需要了解C ++和C#(可以做出一些微妙的差异和陷阱)。一般建议在本机代码和托管代码之间进行接口,但它可以用于将整个库转换为.net。