我是Visual Studio 2010项目配置的新手,但我做了一些研究,仍然不能完全解决这个问题。我有一个Visual Studio解决方案的c++ DLL引用c# DLL。c# DLL引用了一些其他DLL,一些在我的项目内,一些在外部。当我试图编译c++ DLL时,我得到这个警告:

警告MSB3270:正在构建的“MSIL”项目的处理器架构与参考“[内部c# dll]”,“x86”的处理器架构之间不匹配。

它告诉我去配置管理器调整我的架构。c# DLL是用目标平台x86建立的。如果我尝试将其更改为其他东西,如任何CPU,它会抱怨,因为它所依赖的外部dll之一具有平台目标x86。

当我查看配置管理器时,它显示了我的c# DLL作为x86和我的c++项目作为Win32的平台。这似乎是正确的设置;当然,我不希望我的c++项目的项目平台设置为x64,这是唯一的其他选项。

我哪里做错了?


当前回答

c# DLL是用目标平台x86建立的

这就是问题所在,DLL实际上无法选择进程的比特数。这完全由EXE项目决定,这是加载的第一个程序集,所以它的平台目标设置是为进程计数和设置位。

dll没有选择,它们需要与进程位相兼容。如果它们不是,那么当你的代码试图使用它们时,你会得到一个大的爆炸和BadImageFormatException。

因此,对于dll来说,一个很好的选择是AnyCPU,这样它们就可以以两种方式工作。这对于c# dll来说很有意义,它们可以以任何一种方式工作。但当然,不是您的c++ /CLI混合模式DLL,它包含非托管代码,只有在进程以32位模式运行时才能很好地工作。您可以让构建系统生成关于此的警告。这正是你得到的。只是警告,它仍然可以正确构建。

把这个问题撇在一边。将EXE项目的平台目标设置为x86,它将无法与任何其他设置一起工作。并将所有DLL项目保存在AnyCPU中。

其他回答

c# DLL是用目标平台x86建立的

这就是问题所在,DLL实际上无法选择进程的比特数。这完全由EXE项目决定,这是加载的第一个程序集,所以它的平台目标设置是为进程计数和设置位。

dll没有选择,它们需要与进程位相兼容。如果它们不是,那么当你的代码试图使用它们时,你会得到一个大的爆炸和BadImageFormatException。

因此,对于dll来说,一个很好的选择是AnyCPU,这样它们就可以以两种方式工作。这对于c# dll来说很有意义,它们可以以任何一种方式工作。但当然,不是您的c++ /CLI混合模式DLL,它包含非托管代码,只有在进程以32位模式运行时才能很好地工作。您可以让构建系统生成关于此的警告。这正是你得到的。只是警告,它仍然可以正确构建。

把这个问题撇在一边。将EXE项目的平台目标设置为x86,它将无法与任何其他设置一起工作。并将所有DLL项目保存在AnyCPU中。

我解决了这个警告,将“配置管理器”更改为发布(混合平台)。

我在Visual Studio 2012编译SQL Server 2012 SP1 SSIS管道脚本任务时得到了这个警告-直到我安装了SQL Server 2012 SP2。

我在SQLite打开连接时遇到了同样的问题,使用Nuget并安装项目中使用的组件(SQLite)修复了它!尝试以这种方式安装组件并检查结果

一个好的经验法则是“打开dll,关闭ex”,也就是说:

EXE的目标操作系统,通过指定x86或x64。 dll是开放的(即AnyCPU),因此可以在32位或64位进程中实例化它们。

当您将EXE构建为AnyCPU时,您所做的一切都是将使用哪个进程位的决定推迟到操作系统,这将JIT EXE到它喜欢的程度。也就是说,x64操作系统将创建64位进程,x86操作系统将创建32位进程。

将dll构建为AnyCPU可以使它们与任一进程兼容。

有关程序集加载的更多细节,请参见这里。执行摘要如下所示:

AnyCPU -加载为x64或x86程序集,取决于调用进程 X86 -加载为X86汇编;不能从x64进程加载 X64 -加载为X64程序集;不能从x86进程加载