在我的项目中,我必须使用第三方C ++ DLL(而不是COM)。我开发了一个接口C#dll,由我的主程序使用。这是设置:
IDE:VS Express Desktop 2013 x64
Legacy.dll(C ++)Interface.dll(C#.Net4.5 AnyCPU)Program.exe(C# .Net4.5 AnyCPU)
这是我的互操作班:
public static class Legacy
{
// Establish a connection with a protocol channel
// extern “C” long WINAPI LegacyConnect(unsigned long ProtocolID, unsigned long Flags, unsigned long *pChannelID)
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyConnect(Int32 ProtocolId, Int32 Flags, ref Int32 pChannelId);
// Terminate a connection with a protocol channel
// extern “C” long WINAPI LegacyDisconnect(unsigned long ChannelID)
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyDisconnect(Int32 ChannelId);
// General I/O control functions for reading and writing protocol configuration parameters (e.g. initialization, baud rates, programming voltages, etc.)
// extern “C” long WINAPI LegacyIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput)
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyIoctl(Int32 ChannelID, Int32 IoctlId, byte[] pInput, Int32 pOutput);
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyIoctl(Int32 ChannelID, Int32 IoctlId, ref SCONFIG_LIST pInput, Int32 pOutput);
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyIoctl(Int32 ChannelID, Int32 IoctlId, ref SCONFIG_HWTYPE_BAUDRATE pInput, Int32 pOutput);
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyIoctl(Int32 ChannelID, Int32 IoctlId, IntPtr pInput, Int32 pOutput);
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyIoctl(Int32 ChannelID, Int32 IoctlId, ref int pInput, Int32 pOutput);
// Read message(s) from a protocol channel
// extern “C” long WINAPI LegacyReadMsgs(unsigned long ChannelID, Legacy_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout)
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyReadMsgs(Int32 ChannelID, ref Legacy_MSG pMsg, ref Int32 pNumMsgs, Int32 TimeOut);
// Write message(s) to a protocol channel
// extern “C” long WINAPI LegacyWriteMsgs(unsigned long ChannelID, Legacy_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout)
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyWriteMsgs(Int32 ChannelID, ref Legacy_MSG pMsg, ref Int32 pNumMsgs, Int32 TimeOut);
[DllImport("Legacy.dll")]
public static extern LegacyErrCodes LegacyWriteMsgs(Int32 ChannelID, IntPtr pMsg, ref Int32 pNumMsgs, Int32 TimeOut);
}
两个.Net项目最初都以框架形式定位到AnyCPU的框架4.5,一切正常。
我被要求将解决方案降级到目标框架4,幸运的是,没有代码必须在Interface.dll中修改,也没有与它在Program.dll中的使用相关,因此设置变为:
Legacy.dll(C ++)Interface.dll(C#.Net4 AnyCPU)Program.exe(C#.Net4 AnyCPU)
从那时起,每次我的Inteface.dll试图调用C ++ dll函数时,我都会遇到 BadImageFormatException 。
我找到了解决办法:如果我将我的调用程序(Program.exe)设置为仅针对x86 CPU,它会再次运行。
Legacy.dll(C ++)Interface.dll(C#.Net4 AnyCPU)Program.exe(C#.Net4 86)
我只不过是一名高级开发人员,所以我绝对不知道这个问题。为什么会这样?它是一种将我的Program.exe配置恢复到AnyCPU的方法吗?如果没有,这是否真的意味着我的程序即使在64位机器上也会以32位运行?
答案 0 :(得分:4)
BadImageFormatException
很可能是因为尝试加载具有错误" bitness"的可执行文件而导致的。 (例如,在64位进程中加载32位DLL)。如果Legacy.dll
是32位DLL(它似乎基于您提供的信息),您应该简单地编译Program.exe
目标x86
。如果您定位AnyCPU
,则Program.exe
将在64位操作系统上以64位进程执行,如果您要加载32位DLL,则不希望发生这种情况。实际上,在.NET 4.5中,这稍微改变了,因此可执行项目的默认值是使用AnyCPU
但是对于#34;更喜欢32位" (/platform:anycpu32bitpreferred
)解释了为什么在降级到.NET 4时只遇到问题。
这是否真的意味着我的程序即使在64位机器上也会以32位运行?
是的,您的程序加载了32位旧版DLL,即使在64位操作系统上也必须以32位进程执行。只有当您可以获得64位版本的旧DLL时,您的程序才能以64位进程执行。
一般情况下,如果您的代码依赖于仅存在32位或64位的DLL,则应避免定位AnyCPU
,这通常是您进行互操作时的情况。相反,任何具有32位依赖关系的程序集都应该以{{1}}为目标,并且此特定目标应该从依赖关系链一直流向可执行项目。