【问题标题】:Any CPU not available in C++/C# solutionC++/C# 解决方案中不可用的任何 CPU
【发布时间】:2015-04-01 12:55:23
【问题描述】:

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

我将 C++ 项目链接器设置更改为 Force Safe IL Image for both x64 和 x86。

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

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

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

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

【问题讨论】:

  • Managed C++ and AnyCPU 的可能重复项
  • 我不这么认为,因为 C++ 项目生成的 DLL 是 MSIL。所以没有必要在加载 x64 或 x86 时做“奇怪”的事情。我只是不明白为什么我无法将托管 C++ 编译为“任何 CPU”(在配置中)
  • 试图解释特定平台名称是完全当您构建代码时,您知道,在任何平台上运行是一项从未完成的艰巨任务。唯一重要的是 EXE 项目中的抖动覆盖。
  • @ChristopherPainter:这不是该帖子的副本。您建议作为副本的一个是讨论特定于平台的 C++/CLI DLL 的使用,根据平台自动选择。在这里,OP 想要一个与 C#“AnyCPU”程序集具有相同特征的 C++/CLI DLL 程序集。 IE。可以在任何平台上运行的单个程序集。

标签: c# c++ managed anycpu


【解决方案1】:

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

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

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

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

  • CLR 图像类型:只要确保没有明确设置为 IJWPURE

注意事项:

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

【讨论】:

  • 这个答案与我在解决方案中看到的一致。例如,我无法在 MSDN 上找到任何解释 Peter 所写内容的参考,即“您无法在 Visual Studio 中为 C++/CLI 项目创建“AnyCPU”项目类型”
  • 在 VS2015 更新 5 中,这会生成一个编译器警告 D9035,它告诉我们我们确实在编译已过时的托管 C++,并且支持将在未来的版本中删除(尚未尝试 2017,也许这个答案不再有效)。很遗憾,因为这确实是我们想要的,AnyCPU 编译器/链接器配置文件。
  • 这不是一个有效的答案,因为如果您只生成 MSIL,那么无论如何您都不应该用 C++ 编写代码。如果您只使用 .NET Framework 和 MSIL 库编写软件,那么您只会让尝试用 C++ 编写变得困难。我能想象的唯一好处可能是使用 PInvoke 代码,但是警告和非标准/折旧的方法让我放弃了这个解决方案。
【解决方案2】:

为了让 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

【讨论】:

  • 谢谢托比,我已经更新了我的答案,希望能提供更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-17
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 2015-10-25
  • 2012-06-02
相关资源
最近更新 更多