0

我有一段“普通”C++ 代码,我正试图让 C# 客户端可以使用它。我已经用 /CLR 成功编译了这个。我现在知道这还不够:我必须引入托管包装类(“ref”)以使代码可以从托管代码中调用。这个问题是关于在我介绍 ref 类之前发生的事情。

我发现在 C# 项目中可以看到原生 C++ 类,并且我可以编写

MyNativeClass mnc = new MyNativeClass();

...尽管编译器拒绝了对实例调用方法的任何尝试。我发现,当我运行 C# 代码时,从未调用过 MyNativeClass 构造函数——事实上,实例化 mnc 的尝试似乎根本没有产生任何代码,因此完成而没有错误。

C# 是如何解释我项目中的本机类型的?为什么编译器显然允许我实例化一个实例?为什么方法与类型本身不同?

4

1 回答 1

1

您犯了两个错误以使此代码正常工作。首先是您声明了 C++ 类public,如下所示:

 public class MyNativeClass {};

这不是 C++ 中有意义的语法,但 C++/CLI 编译器允许。省略public会在您的 C# 代码中产生一条错误消息,CS0122:“Foo is inaccessible due to its protection level”。

第二个错误是你编译你的本地 C++ 类时使用 /clr 有效。效果很好,任何符合 C++03 的代码都可以编译为 IL,并通过抖动实时编译为机器代码,就像托管代码一样。并且执行也很好。但是这样做效率不高,您失去了使用编译时优化器来生成最佳代码的优势。它仍然得到优化,但现在由于抖动,它没有像 C++ 代码优化器那样出色的工作时间。您可以通过将 C++ 代码移动到单独的源代码文件中来避免这种情况,这样您就可以在 /clr 不生效的情况下对其进行编译。或者通过使用源代码中管理的#pragma。

无论如何,您最终得到的是一个程序集,其中确实包含任何托管编译器都可以看到的 MyNativeClass 声明。通过在程序集上运行 ildasm.exe,您可以自己看到一些东西。您会看到它被嵌入为值类型类型。只是一个没有构造函数和方法的字节块。从托管的角度来看,这对于 C++ 对象来说是一个不错的匹配,只是可以存储在任何可以存储值类型的地方的字节。在 C# 中声明该类型的变量有效,但没有做任何有用的事情,它只是创建所有字节设置为 0 的 blob。此声明的唯一可能用途是您可以声明指向该类的类型化指针并传递它周围,​​仅此而已。

于 2013-02-21T11:56:04.860 回答