在玩弄混合语言程序集(例如这里或这里)时,我遇到了几个奇怪的链接错误。我不是在寻找"不要那样做"的建议或替代方案,而是想了解这些错误应该意味着什么,因为从表面上看都没有多大意义。
C# 代码:
// csppStub.cs
public static partial class To
{
static partial void Do();
extern public static bool Done();
}
C++代码:
// cspp.cpp
public ref class To abstract sealed
{
// lnk2022 metadata operation failed (801311D6):
// Differing number of methods in duplicated types (To): (0x02000002).
static void Do() { }
// lnk2022 metadata operation failed (801311D8):
// Differing number of parameters in duplicated method (types: To; methods: Done): (0x06000001).
public: static bool Done() { return true; }
};
VS 2015 项目文件:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>cspp</ProjectName>
<ProjectGuid>{A6FF913B-C27A-4CBC-A847-B15CFA7AE80F}</ProjectGuid>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CLRSupport>true</CLRSupport>
</PropertyGroup>
<Import Project="$(VCTargetsPath)Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>$(OutDir)csppStub.netmodule;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<ClCompile>
<CompileAsManaged>true</CompileAsManaged>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="cspp.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsManaged>
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Async</ExceptionHandling>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="csppStub.cs">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">csc /target:module /out:$(OutDir)csppStub.netmodule csppStub.cs</Command>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)csppStub.netmodule</Outputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
构建输出:
Error LNK2022 metadata operation failed (801311D8): Differing number of parameters in duplicated method (types: To; methods: Done): (0x06000001).
Error LNK2022 metadata operation failed (801311D6): Differing number of methods in duplicated types (To): (0x02000002).
链接器对您要执行的操作感到非常困惑,因此其诊断并不出色。 C++/CLI 代码中的一个常见问题是,它可能在多个对象文件中遇到相同的 ref 类声明。由 #include 指令引起。 在 C# 中不会发生什么,partial
关键字在编译时解析。
链接器必须对此执行一些操作,它需要将这些重复项筛选为可以在元数据中发出的单个定义。它执行测试以确保类定义完全相同。LNK2022,当他们不是。 造成这种情况的常见原因是宏或不同的编译选项。
但在这种情况下,重复项来自 C# 和 C++/CLI 声明。 放弃所有的希望,那永远不会是对手。extern
关键字不会执行您认为它所做的事情,它是抖动的指令,并告诉它需要在其他地方找到该函数。 它知道的其他地方并不多,也不可扩展,仅限于 CLR 实现的函数、[DllImport] 声明和 COM 互操作。
元数据中根本没有类似于partial
的机制。 您必须考虑在 .NET 中采用通常无聊的方式、继承和多态性。 C++/CLI 类可以使用 C# 类作为其基,并且可以abstract
C# 类。