我有一个包装C ++ DLL的CLI代码 当我尝试在调试模式下编译它时,我收到以下错误:
错误22错误LNK2022:元数据操作失败(8013118D):
不一致的布局信息复杂类型.... MSVCMRTD.lib(locale0_implib.obj)
奇怪的是,在发布模式下,它编译正常并且正常工作 我可以看到导致问题的唯一区别是当我改变时:
配置属性 - > C / C ++ - >代码生成 - >运行时库
当它设置为:Multi-threaded Debug DLL (/MDd)
时,它会抛出错误
当它设置为:Multi-threaded DLL (/MD)
时,它编译得很好。
相同的设置适用于项目中的所有其他DLL(CLI和C ++),并且它们继承了相同的属性。
我正在使用VS2010。
那么,我该如何解决这个问题?
我能否解释为什么会发生这种情况?
更新
我基本上试图改变项目属性中的每个选项而没有运气。
我在某处读到过这可能是由于同名类型的重复声明造成的 但是在CLI文件中我明确地从std。
调用std :: string等还有其他想法吗?
更新
一些错误的复制粘贴:
error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_val<char,std::allocator<char> >): (0x02000097). E:\MyProject....\MSVCMRTD.lib(locale0_implib.obj) DllName
error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_iterator<char,std::char_traits<char>,std::allocator<char> >): (0x02000091). E:\MyProject....\MSVCMRTD.lib(locale0_implib.obj) AnotherDllName
请注意, MSVCMRTD.lib 文件实际上是用于编译的MS文件,实际上并不在我的项目中(也不应该)
更新
如果这有帮助,这里是链接器命令行:
/ OUT:“E:\ blah.CLI.dll”/ INCREMENTAL / NOLOGO / LIBPATH:“e:\ blah \ Output \” / LIBPATH: “E:\等等\ lib_64” / LIBPATH:“blah \ Lib_64 \”/ DLL “e:\ Otheblaf.lib”/ MANIFEST /ManifestFile:"x64\Debug\blah.CLI.dll.intermediate.manifest” / ALLOWISOLATION / MANIFESTUAC:“电平= 'asInvoker' uiAccess ='false'“/ DEBUG /PDB:"E:\blah.CLI.pdb” / SUBSYSTEM:WINDOWS / OPT:NOREF / OPT:NOICF /PGD:"E:\blah.CLI.pgd“ / TLBID:1 / DYNAMICBASE:NO / FIXED:NO / MACHINE:X64 / ERRORREPORT:QUEUE
有效的版本:
/ OUT:“E:\ blah.CLI.dll”/ INCREMENTAL:NO / NOLOGO / LIBPATH:“E:\ blah \” / LIBPATH: “E:\等等\输出\” / LIBPATH:“E:\ blah \ lib_64”/ DLL “Configuration.lib”“kernel32.lib” “user32.lib”“gdi32.lib” “winspool.lib”“comdlg32.lib” “advapi32.lib”“shell32.lib” “ole32.lib”“oleaut32.lib”“uuid.lib” “odbc32.lib”“odbccp32.lib” “E:\ blah.lib”/ MANIFEST /ManifestFile:"blah.CLI.dll.intermediate.manifest” / ALLOWISOLATION / MANIFESTUAC:“电平= 'asInvoker' uiAccess ='false'“/ DEBUG /PDB:"E:\blah.CLI.pdb” / SUBSYSTEM:WINDOWS / OPT:REF / OPT:ICF /PGD:"E:\blah.CLI.pgd“/ LTCG / TLBID:1 / DYNAMICBASE / FIXED:NO / MACHINE:X64 / ERRORREPORT:QUEUE
答案 0 :(得分:2)
您在构建项目时是使用自定义生成文件还是自定义编译器参数?这可能会以难以想象的方式搞乱项目。
[a]在构建该DLL期间,pragma pack设置可能被设置为自定义编译器设置,这导致windows标准头中的结构被错误地打包导致大小不匹配。易于修复..检查cl.exe的-Zp设置
这种情况可以解决结构是您自己的自定义结构或类之一的情况。
http://msdn.microsoft.com/en-us/library/xh3e3fd0%28v=VS.71%29.aspx
[b]另一种可能发生这种情况的情况是,其中一个头文件包含windows standrd头文件并且pragma pack尚未恢复。然后,这将错误的包信息传播到标准标题,导致与上述相同的问题。通常很容易通过首先包含所有(通过简化方式)窗口标题来解决,以便稍后跳过它们。
希望这有帮助。
答案 1 :(得分:1)
终于得到了解决方案:
最后,这是boost::lexical_cast<std:string>
.Net对象使用某些 std :: 对象时出现错误。 (在我的例子中,错误消息中显示了std :: string)。
这是因为当他们创建这个框架时,他们重新发明了一些类(std :: string就是其中之一)但是在调试版本中没有正确地完成它。
班级的签名有点不同。
MSDN相关文章 - Ambiguous References
因此,解决方案是从.NET对象中“隐藏”错误的类。
创建一个C ++级别的包装类,它将包装原始类的函数并强制转换 错误的类类型到正确编译的其他类类型。
确保在包装器类的头文件中没有引用或包含错误的类类型。 (可以谨慎Forward reference/decleration)来完成 使用VS2010,您可以在没有/ clr的情况下显式编译非托管包装.cpp文件。
然后,您可以使用托管ref类正确使用包装器类。
另一个选项
将lexical_cast<std::string>
替换为:
ostringstream os;
os << i;
return os.str();
答案 2 :(得分:0)
当我将项目转换为64位时,我遇到了这个链接错误。我的修复是配置属性&gt; C / C ++ &gt; 代码生成&gt; 结构成员对齐&gt; 16字节(/ Zp16)
答案 3 :(得分:-1)
确保在编译到调试模式之前清理构建。
答案 4 :(得分:-1)
我希望link对您有所帮助。 在此MSDN建议在目标文件上运行'ildasm -tokens'以查找哪些类型具有error_message中列出的标记,并查找差异。
Here是ildasm exe的一些输入。
答案 5 :(得分:-1)
我发现我的项目中使用的WINVER与我链接的库中使用的WINVER不同。同步这些常量为我解决了这个问题。