C+中不可用的任何CPU+/C#解决方案 我有一个包含C++和托管C++项目的解决方案。 它在解决方案平台x64和x86中编译。因为它是C++管理的,我想创建一个“任何CPU”的解决方案,并摆脱旧的。 我改变了C++项目链接器设置,以强制X64和x86的安全IL图像。

C+中不可用的任何CPU+/C#解决方案 我有一个包含C++和托管C++项目的解决方案。 它在解决方案平台x64和x86中编译。因为它是C++管理的,我想创建一个“任何CPU”的解决方案,并摆脱旧的。 我改变了C++项目链接器设置,以强制X64和x86的安全IL图像。,c#,c++,managed,anycpu,C#,C++,Managed,Anycpu,接下来,使用Configuration Manager,我创建了一个名为“任意CPU”的新解决方案平台。接下来,我添加了一个项目平台,也称为“任意CPU” 我把所有的C项目设置成“任何CPU”,但是对于C++,我不能这么做。项目平台“任何CPU”不在下拉列表中,也没有“新建…”选项 VS对它很熟悉,所以我保持原样并开始构建。令我惊讶的是,即使C++平台是X64,结果DLL(来自C++项目)也是MSIL。编译x32时也会发生同样的情况,生成的DLL位于MSIL中 有什么好处? 为什么我不能将C++

接下来,使用Configuration Manager,我创建了一个名为“任意CPU”的新解决方案平台。接下来,我添加了一个项目平台,也称为“任意CPU”

我把所有的C项目设置成“任何CPU”,但是对于C++,我不能这么做。项目平台“任何CPU”不在下拉列表中,也没有“新建…”选项

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

有什么好处?
为什么我不能将C++项目设置为“任何CPU”?

< P>。据我所知,在VisualStudio中不能为C++或CLI项目创建“ANYCPU”项目类型。但是,您可以配置C++/CLI项目(在“Win32”项目类型下),使其编译为纯安全的MSIL,而无需目标平台。这样做将允许您的C++/CLI DLL程序集与“AnyCPU”C#项目一起使用。也就是说,它实际上是“AnyCPU”,即使它在Configuration Manager中不是它的实际名称

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

  • 公共语言运行时支持:
    Safe MSIL公共语言运行时支持(/clr:Safe)
在“链接器”项目设置中:

  • CLR图像类型:只需确保未明确将其设置为
    IJW
    PURE
注:

  • 通过使用“安全”项目类型,一些似乎会影响平台类型的编译器和链接器选项将被忽略。也就是说,您不必将所有内容都设置为非特定的平台类型。就在上面。但是,如果能让您感觉更好,您可以将其他选项设置为适当的选项。:)
  • “安全”将阻止使用指针。如果这是一个重要的问题,显然可以通过一个更复杂的过程来解决。有关详细信息,请参阅
  • 不要忘记,默认情况下,VisualStudio将创建C#项目,即使它们是“AnyCPU”,即使它们在64位操作系统上执行,也将作为32位进程启动。如果依赖项是x86而不是预期的纯/安全MSIL,则这可能隐藏平台不匹配问题。需要注意的是(您可以通过取消选中C#project的“Build”项目属性页面中的“preference 32-bit”选项来控制这一点)

为了使C++功能被C语言的DLL消耗,C++项目必须同时生成DLL的x86和x64版本。不能从使用AnyCPU设置编译的C#dll中仅引用x86或x64 dll

获取ActudioDLL以使用C++ DLL的窍门是在运行时确保程序集不能加载C++ DLL,然后订阅AppDealEngulySe解析事件。当程序集尝试加载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;
}
事件处理程序如下所示:

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++功能。


我不认为它是复制的,因为从C++项目中得到的DLL是MSIL。因此,在加载x64或x86时不需要做“奇怪”的事情。我无法理解为什么我不能编译管理C++作为“任何CPU”(在配置中)试图解释当构建代码时,特定的平台名称完全无关,你知道,在任何平台上运行是一个从未完成的艰巨任务。唯一重要的是EXE项目中的抖动覆盖。@ChristopherPaint:这不是那篇文章的副本。您作为副本提出的建议是讨论特定于平台的C++/CLI DLL的使用,这些DLL是根据平台自动选择的。这里,OP需要一个与C#“AnyCPU”程序集具有相同特性的C++/CLI DLL程序集。也就是说,可以在任何平台上运行的单个程序集。这个答案与我在解决方案中看到的情况一致。我无法找到解释Peter所写内容的MSDN示例参考,即VS2015更新5中的“无法在Visual Studio中为C++/CLI项目创建“AnyCPU”项目类型”,这将生成编译器警告D9035,它告诉我们,我们正在编译管理C++,它是Mube的,并且支持将在未来的版本中被删除(没有尝试2017,也许这个答案不再有效)。羞愧,因为这是我们真正想要的,一个ANYCPU编译器/链接器配置文件。这不是一个有效的答案,因为如果你只生成MSIL,那么你不应该在C++中编写代码。如果只使用.NETFramework和MSIL库编写软件,那么只在C++中编写就很困难。我能想象的唯一好处可能是使用PInvoke代码,但警告和非标准/降价的方法使我放弃了这个解决方案。感谢Toby,我更新了我的答案,希望它能提供更多信息。