依赖于C ++ / CLI的任何CPU依赖于本机C dll(c ++ / cli的任何cpu)

时间:2011-10-11 14:43:33

标签: c# c c++-cli 64-bit x86

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

以下是现在整理的方式: - 原生C .lib:x86和64bit。

  • 1个包含2个项目的解决方案:
    • C ++ / CLI包装器项目,链接到本机C .lib
    • C#项目引用C ++ / CLI项目

我的问题来自于我需要C#来定位“任何CPU”。但是这个选项在C ++ / CLI中不可用,因为它直接编译为本机代码。

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

我的问题是:

  • 如何告诉C ++ / CLI项目基于目标平台链接到哪个.lib?
  • 如何告诉C#项目哪个C ++ / CLI dll可以根据目标平台进行引用?

让我添加一个x86或x64客户端使用的 C#项目CLASS LIBRARY

我希望我的问题足够明确。任何帮助将不胜感激!

更新基于:Conditional references in .NET project, possible to get rid of warning? ...

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

<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>

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

2 个答案:

答案 0 :(得分:21)

你所描述的被称为“并排组装”(同一组件的两个版本,一个32和另一个64位)......我认为你会发现这些有用:

编辑 - 根据评论:

在这里,您可以找到完全符合您的方案的演练(.NET DLL包装引用本机DLL的C ++ / CLI DLL)http://scottbilas.com/blog/automatically-choose-32-or-64-bit-mixed-mode-dlls/

答案 1 :(得分:0)

对我来说,解决方案如下:

  1. 构建x64位版本的C ++库以输出文件xxx.x64.dll

  2. 构建x86位(Win32平台)版本的C ++库以输出文件xxx.x86.dll

  3. 将它们作为内容文件添加到我的包装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>
    
  4. 在C#中,从x86和x64库版本导入函数。例如:

        [DllImport("xxx.x86.dll", EntryPoint = "FunctionName", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern void FunctionNamex86();
        [DllImport("xxx.x64.dll", EntryPoint = "FunctionName", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern void FunctionNamex64();
    
  5. 在C#实现函数中,该函数根据当前平台调用正确的重载。例如:

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

  7. 要将其作为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>
    

答案主要基于:Using a 32bit or 64bit dll in C# DllImport