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

发布于 12-09 09:38 字数 1813 浏览 0 评论 0 原文

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

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

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

我的问题来自于我需要 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?

让我补充一点,C# 项目是一个供 x86 或 x64 客户端使用的 CLASS LIBRARY

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

更新基于:.NET 项目中的条件引用,可以摆脱警告吗?...

所以现在我已经使用条件引用 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>

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

Here's my problem.
I am wrapping a C dll in C#. To do this, I am first writing a C++/CLI wrapper. The native C library is linked to the C++/CLI wrapper. (Linker properties in C++/cli project).

Here's how it is all organised now:
- The native C .lib: both x86 and 64bit.

  • 1 solution containing 2 projects:
    • C++/CLI wrapper project to which is linked native C .lib
    • C# project referencing C++/CLI project

My problem comes from the fact that I need C# to target "Any CPU". But this option is not available in C++/CLI since it compiles directly to native code.

My idea to solve this is:
- Compile C++/CLI wrapper in x86 and then change the config and compile to 64 bit. When it compiles, I would like to tell it which dll to take based on the platform. ie: if compiling in 64bit, link 64 bit native C dll, else if x86, link x86 native C.
- With this done, I should then be able to have Any CPU target in my C# platform. Here again, instead of referencing my C++/CLI wrapper project, I would reference the required dll based on the target platform.

My questions are:

  • How to I tell the C++/CLI project which .lib to link to based on the target platform?
  • How to I tell the C# project which C++/CLI dll to reference based on the target platform?

Let me add that the C# project a CLASS LIBRARY to be used by an x86 or x64 client.

I hope my question is clear enough. Any helps would be appreciated !

UPDATE based on:Conditional references in .NET project, possible to get rid of warning?...

So now I've edited my .csproj file using a condition to reference the dll as follows:

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

Unfortunately this doesn't work as the $(Platform) is set to AnyCPU...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

⊕婉儿 2024-12-16 09:38:38

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

编辑 - 根据评论:

在这里您可以找到适合您的场景的演练:http://www.thescarms.com/dotnet/Assembly.aspx archive.org/web/20180118101655/http://scottbilas.com/blog/automatically-choose-32-or-64-bit-mixed-mode-dlls/” rel="nofollow noreferrer">.NET DLL 包装引用本机 DLL 的 C++/CLI DLL

What you describe is known as "side-by-side assembly" (two versions of the same assembly, one 32 and the other 64 bit)... I think you will find these helpful:

EDIT - as per comment:

Here you can find a walkthrough for exactly your scenario: .NET DLL wrapping C++/CLI DLL referencing a native DLL

晨敛清荷 2024-12-16 09:38:38

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

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

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

  3. 将它们作为内容文件添加到我的包装器 C# 项目中。例如:

    ;
      <内容包含=“..\..\$(配置)\xxx.x86.dll”链接=“xxx.x86.dll”>
        <复制到输出目录>保留最新的
      
      <内容包含=“..\..\$(配置)\xxx.x64.dll”链接=“xxx.x64.dll”>
        <复制到输出目录>保留最新的
      
    
    
  4. 在 C# 中,从 x86 和 x64 库版本导入函数。例如:

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

     public static void 函数名()
        {
            如果(环境.Is64BitProcess)
                函数名称x64();
            别的
                函数名x86();
        }
    
  6. 现在 C# 项目可以构建为“任何 CPU”并由其他多平台项目使用。

  7. 要将其作为 NuGet 包分发,我使用以下 NuSpec 配置:

    
    <封装>
        <元数据>
            <内容文件>
                >
                >
            
        
        <文件>
            <文件 src="Release/C#Wrapper.dll" target="lib" /> 
            <文件 src="Release/xxx.x64.dll" target="内容" /> 
            <文件 src="Release/xxx.x86.dll" target="内容" /> 
            <文件 src="Release/xxx.x64.dll" target="contentFiles/any/any" /> 
            <文件 src="Release/xxx.x86.dll" target="contentFiles/any/any" /> 
        
    
    

答案主要基于: 在 C# DllImport 中使用 32 位或 64 位 dll

For me solution was following:

  1. Build x64 bit version of C++ library to output file xxx.x64.dll

  2. Build x86 bit (Win32 platform) version of C++ library to output file xxx.x86.dll

  3. Add them as content files to my wrapper C# project. Ex.:

    <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. In C# Import functions from both x86 and x64 library versions. Ex.:

        [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. In C# implement function that calls correct overload based on current platform. Ex.:

        public static void FunctionName()
        {
            if (Environment.Is64BitProcess)
                FunctionNamex64();
            else
                FunctionNamex86();
        }
    
  6. Now C# project can be built as "Any CPU" and used by other multiplatform projects.

  7. To distribute it as NuGet package, I use following NuSpec configuration:

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

Answer is mostly based on: Using a 32bit or 64bit dll in C# DllImport

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文