18

我有一个包含 C# 和托管 C++ 项目的解决方案。它在解决方案平台 x64 和 x86 中编译。由于它是托管的 C++,我想创建一个“任何 CPU”解决方案并摆脱旧的解决方案。

我将 C++ 项目链接器设置更改为针对 x64 和 x86 的强制安全 IL 映像。

接下来,我使用配置管理器创建了一个名为“Any CPU”的新解决方案平台。接下来,我添加了一个项目平台,也称为“Any CPU”。

我继续将所有 C# 项目设置为“任何 CPU”,但对于 C++,我不能这样做。项目平台“Any CPU”不在下拉列表中,也没有选项“New...”。

VS 对此很满意,所以我保持原样并开始构建。令我惊讶的是,结果 DLL(来自 C++ 项目)是 MSIL,即使 C++ 的平台是 x64。编译 x32 时也会发生同样的情况,生成的 DLL 位于 MSIL 中。

是什么赋予了?为什么我不能将 C++ 项目设置为“任何 CPU”?

4

2 回答 2

17

据我所知,您不能在 Visual Studio 中为 C++/CLI 项目创建“AnyCPU”项目类型。但是,您可以配置您的 C++/CLI 项目(在“Win32”项目类型下),以便它编译为纯的、安全的 MSIL,而无需目标平台。这样做将允许您的 C++/CLI DLL 程序集与“AnyCPU”C# 项目一起使用。即它实际上是“AnyCPU”,即使这不是它在配置管理器中的实际名称。

在“C/C++”项目设置中:

  • 公共语言运行时支持:Safe MSIL Common Language RunTime Support (/clr:safe)

在“链接器”项目设置中:

  • CLR 图像类型:只需确保未将其显式设置为IJWPURE

笔记:

  • 通过使用“安全”项目类型,一些似乎影响平台类型的编译器和链接器选项将被忽略。即,您不必将所有内容都设置为非特定平台类型。就如上。但是,如果它让您感觉更好,您可以将其他选项设置为适当的值。:)
  • “安全”将阻止使用指针。如果这是一个重要的问题,显然可以通过更复杂的过程来完成。请参阅从 C++/CLI 项目创建纯 MSIL 程序集?详情。
  • 不要忘记默认情况下,Visual Studio 将创建 C# 项目,即使它们是“AnyCPU”并且即使它们在 64 位操作系统上执行,也会作为 32 位进程启动。如果依赖项是 x86 而不是预期的纯/安全 MSIL,这可以隐藏平台不匹配问题。请注意(您可以通过取消选中 C# 项目的“构建”项目属性页面中的“首选 32 位”选项来控制这一点)。
于 2015-02-03T04:39:20.237 回答
7

为了让 C# dll 使用 C++ 功能,C++ 项目必须同时生成 x86 和 x64 版本的 dll。无法从使用 AnyCPU 设置编译的 C# dll 中仅引用 x86 或 x64 dll。

让 AnyCPU dll 与 C++ dll 一起使用的技巧是在运行时确保程序集无法加载 C++ dll,然后订阅 AppDomain AssemblyResolve 事件。当程序集尝试加载 dll 并失败时,您的代码就有机会确定需要加载哪个 dll。

订阅事件看起来像这样:

System.AppDomain.CurrentDomain.AssemblyResolve += Resolver;

事件处理程序看起来像这样:

System.Reflection.Assembly Resolver(object sender, System.ResolveEventArgs args)
{
     string assembly_dll = new AssemblyName(args.Name).Name + ".dll";
     string assembly_directory = "Parent directory of the C++ dlls";

     Assembly assembly = null;
     if(Environment.Is64BitProcess)
     {
            assembly = Assembly.LoadFile(assembly_directory + @"\x64\" + assembly_dll);
     }
     else
     {
            assembly = Assembly.LoadFile(assembly_directory + @"\x86\" + assembly_dll);
     }
     return assembly;
}

我创建了一个简单的项目,演示如何从 AnyCPU dll 访问 C++ 功能。

https://github.com/kevin-marshall/Managed.AnyCPU

于 2016-11-22T17:32:02.350 回答