C# 任何依赖于C++/依赖于本机C dll的CLI(C+;+;/CLI的任何cpu)

C# 任何依赖于C++/依赖于本机C dll的CLI(C+;+;/CLI的任何cpu),c#,c,c++-cli,64-bit,x86,C#,C,C++ Cli,64 Bit,X86,这是我的问题。 我正在用C#包装一个C dll。为此,我首先编写一个C++/CLI包装器。本机C库链接到C++/CLI包装器。(C++/cli项目中的链接器属性) 以下是现在的组织方式: -本机C.lib:x86和64位 1个解决方案包含2个项目: 链接到本机C.lib的C++/CLI包装器项目 C#项目引用C++/CLI项目 我的问题来自这样一个事实:我需要C#来瞄准“任何CPU”。但此选项在C++/CLI中不可用,因为它直接编译为本机代码 我解决这个问题的想法是: -在x86中编译C

这是我的问题。 我正在用C#包装一个C dll。为此,我首先编写一个C++/CLI包装器。本机C库链接到C++/CLI包装器。(C++/cli项目中的链接器属性)

以下是现在的组织方式: -本机C.lib:x86和64位

  • 1个解决方案包含2个项目:
    • 链接到本机C.lib的C++/CLI包装器项目
    • C#项目引用C++/CLI项目
我的问题来自这样一个事实:我需要C#来瞄准“任何CPU”。但此选项在C++/CLI中不可用,因为它直接编译为本机代码

我解决这个问题的想法是: -在x86中编译C++/CLI包装,然后更改配置并编译为64位。当它编译时,我想告诉它根据平台使用哪个dll。ie:如果以64位编译,则链接64位本机C dll;如果是x86,则链接x86本机C dll。 -这样,我就可以在我的C#平台中拥有任何CPU目标。在这里,我将引用基于目标平台的所需dll,而不是引用我的C++/CLI包装器项目

我的问题是:

  • 如何根据目标平台告诉C++/CLI项目要链接到哪个.lib
  • 如何告诉C#项目基于目标平台引用哪个C++/CLI dll
让我补充一点,C#计划一个类库,供x86或x64客户机使用

我希望我的问题足够清楚。任何帮助都将不胜感激

根据以下内容更新

现在,我已使用引用dll的条件编辑了.csproj文件,如下所示:

<ItemGroup>
    <Reference Include="AlibCppWrapper, Version=1.0.4303.21410, Culture=neutral, PublicKeyToken=c0c17a53adc44091, processorArchitecture=AMD64"
               Condition="$(Platform) == 'x64'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\x64\Debug\AlibCppWrapper.dll</HintPath>
    </Reference>
    <Reference Include="AlibCppWrapper, Version=1.0.4303.21410, Culture=neutral, PublicKeyToken=c0c17a53adc44091, processorArchitecture=x86"
               Condition="$(Platform) == 'x86'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\Debug\AlibCppWrapper.dll</HintPath>
    </Reference>
  </ItemGroup>

假的
..\x64\Debug\AlibCppWrapper.dll
假的
..\Debug\AlibCppWrapper.dll

不幸的是,这不起作用,因为$(平台)被设置为AnyCPU…

您所描述的被称为“并行程序集”(同一程序集的两个版本,一个32位,另一个64位)。。。我想你会发现这些很有帮助:

编辑-根据评论:


在这里,您可以找到一个完全适合您的场景的演练:

针对我的解决方案如下:

< L> > p>构建x64位版本的C++库,输出文件xxx .x64 .dll < /p> < p>编译x86位(win32平台)的C++库版本,输出文件xxx .x86 .dll < /p>
  • 将它们作为内容文件添加到我的包装器C#项目中。例:

    <ItemGroup>
      <Content Include="..\..\$(Configuration)\xxx.x86.dll" Link="xxx.x86.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
      <Content Include="..\..\$(Configuration)\xxx.x64.dll" Link="xxx.x64.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
    
  • 在C#中,实现基于当前平台调用正确重载的函数。例:

        public static void FunctionName()
        {
            if (Environment.Is64BitProcess)
                FunctionNamex64();
            else
                FunctionNamex86();
        }
    
  • 现在C#项目可以构建为“任何CPU”,并被其他多平台项目使用

  • 为了将其作为NuGet包分发,我使用以下NuSpec配置:

    <?xml version="1.0"?>
    <package>
        <metadata>
            <contentFiles>
                <files include="any/any/xxx.x64.dll" buildAction="None" copyToOutput="true" />
                <files include="any/any/xxx.x86.dll" buildAction="None" copyToOutput="true" />
            </contentFiles>
        </metadata>
        <files>
            <file src="Release/C#Wrapper.dll" target="lib" /> 
            <file src="Release/xxx.x64.dll" target="content" /> 
            <file src="Release/xxx.x86.dll" target="content" /> 
            <file src="Release/xxx.x64.dll" target="contentFiles/any/any" /> 
            <file src="Release/xxx.x86.dll" target="contentFiles/any/any" /> 
        </files>
    </package>
    
    
    

  • 答案主要基于:

    我看不出有问题。如果您希望以x64和x86为目标,则需要为每个平台(C/C++)编译单独的文件,并根据所处的平台在C#应用程序中引用正确的库。您还可以通过使用对x86或x64编译库的引用来决定是否强制使用某个平台。我没有看到一个“?”可以随意编辑你的问题,把你的问题弄清楚。“任何CPU”都是硬要求吗?懒惰程序员的解决方案是只为x86编译,因为它在x64中运行。是的,这是一个硬要求。C#项目实际上是一个供客户机和服务器使用的库,可以安装在64位或x86上。这是一个部署问题。本机DLL不是问题,您可以为它们指定不同的名称,并在链接器的附加依赖项设置中指定它们。关键在于C++/CLI程序集。CLR可以根据processorArchitecture属性自动选择正确的程序集,但这需要将它们部署到GAC。这需要两名安装人员。因为您无论如何都需要它们,所以简单的解决方案是只提供两个不同的安装程序,一个用于32位机器,另一个用于64位机器。每个都部署了正确风格的DLL。@IlianPinzon-如果我的C#库是x86,那么它就不能被在x64体系结构上编译的具有任何CPU的客户端程序调用。。。将此客户端更改为x86是不可能的。@nche-这是您应该接受的答案。这将完全满足您的需求,是一个优雅的解决方案。使应用程序同时支持x64和x86平台的正确方法是制作单独的程序集。如果应用程序引用32位库程序集,则它不能是x64进程。第一个链接中的并行解决方案似乎适合我的问题,但问题是我的C#项目是dll,而不是exe。因此,我没有任何main,因为我可以通过编程定义要加载的与体系结构相关的dll。例如,是否可以使用条件引用?ie:在我的C++/cli项目中,根据体系结构链接适当的C dll(x86或x64)。。。对于C#项目也是如此(根据体系结构链接足够的C++/cli引用)…如果我的C#项目是一个dll,这个解决方案将是完美的。然后我将动态加载dll。但在我的例子中,它是一个类库。所以我无法动态加载所需的底层dll,可以吗?…对不起-您想要不可能的。。。不可能比上面描述的更多。。。如果以上内容有任何帮助,请投票/标记为已接受…嗯。。所以很抱歉-你想知道这个答案被接受为答案的原因吗?因为,如果你不理会这些评论,我会认为16个人和OP正在投票,并接受一个解决一个截然不同的问题/考虑/问题的答案。
    <?xml version="1.0"?>
    <package>
        <metadata>
            <contentFiles>
                <files include="any/any/xxx.x64.dll" buildAction="None" copyToOutput="true" />
                <files include="any/any/xxx.x86.dll" buildAction="None" copyToOutput="true" />
            </contentFiles>
        </metadata>
        <files>
            <file src="Release/C#Wrapper.dll" target="lib" /> 
            <file src="Release/xxx.x64.dll" target="content" /> 
            <file src="Release/xxx.x86.dll" target="content" /> 
            <file src="Release/xxx.x64.dll" target="contentFiles/any/any" /> 
            <file src="Release/xxx.x86.dll" target="contentFiles/any/any" /> 
        </files>
    </package>