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

本文关键字:任何 CLI CPU 依赖于 c++ 用于 本机 dll | 更新日期: 2023-09-27 18:10:53

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

现在是这样组织的:-本机C .lib: x86和64位。

  • 1个方案包含2个项目:
    • c++/CLI包装器项目,本机C .lib
    • c#项目引用c++/CLI项目

我的问题来自于我需要c#来瞄准"任何CPU"这一事实。但是这个选项在c++/CLI中不可用,因为它直接编译为本机代码。

我解决这个问题的想法是:—在x86环境下编译c++/CLI wrapper,然后修改配置,编译为64位。当它编译的时候,我想根据平台告诉它使用哪个dll。即:如果在64位编译,链接64位原生C的dll,否则如果是x86,链接x86原生C。-完成后,我应该能够在我的c#平台上有任何CPU目标。这里,我将再次引用基于目标平台的所需dll,而不是引用我的c++/CLI包装器项目。

我的问题是:

  • 我如何告诉c++/CLI项目哪个。lib链接到基于目标平台?
  • 我如何告诉c#项目哪个c++/CLI dll引用基于目标平台?

让我补充一下, c#投射了一个类库供x86或x64客户端使用。

我希望我的问题足够清楚。如有任何帮助,不胜感激!

UPDATE基于:.NET项目中的条件引用,可能摆脱警告…

所以现在我已经编辑了我的.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…

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

你所描述的就是所谓的"并排组装"。(同一个程序集的两个版本,一个32位,另一个64位)…我想你会发现这些很有帮助:

  • 使用并行程序集加载x64或x32版本的DLL
  • http://blogs.msdn.com/b/gauravseth/archive/2006/03/07/545104.aspx
  • http://www.thescarms.com/dotnet/Assembly.aspx

编辑-按注释:

在这里你可以找到一个完全适合你的场景的演练:.NET DLL包装c++/CLI DLL引用本地DLL

我的解决方案如下:

  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>
    
在c#中使用32位或64位dll