为32位和64位非托管DLL创建托管包装器

时间:2010-01-14 14:26:41

标签: c# visual-studio 64-bit unmanaged x86-64

我们正在围绕非托管DLL创建一个C#包装器。非托管DLL有32和64位版本。我们将托管包装器保留在自己的项目中,以便我们可以将其构建为单独的组件并在整个解决方案中重用它。

然而,这会导致一些问题。由于非托管DLL对于32位和64位版本具有相同的名称,因此我们无法将正确的非托管DLL移动到输出(bin)目录。如果构建配置是x86,我们要复制32位版本,使用x64复制64位。只需一个处理器架构,这很容易实现。我们只在项目中包含非托管DLL,并在文件上将copy local设置为true。但是因为我们需要更加棘手的目标。

我们发现此链接Targeting both 32bit and 64bit with Visual Studio in same solution/project但这似乎引用了计算机上已存在的某些DLL。我们希望将DLL的正确版本复制到输出目录(bin)。

有关如何解决此问题的任何提示或技巧都非常受欢迎。

5 个答案:

答案 0 :(得分:5)

我刚刚使用FreeImage库的.Net包装器解决了同样的问题。我所做的是创建两个构建配置,一个用于x86,另一个用于x64,用于引用托管包装器的项目。我在项目文件的AfterBuild目标中添加了msbuild条件复制部分,如下所示:

  <Target Name="AfterBuild">
    <Copy Condition="'$(Platform)' == 'X86'" SourceFiles="$(MSBuildProjectDirectory)\Resources\x86\FreeImage.dll" DestinationFolder="$(TargetDir)" />
    <Copy Condition="'$(Platform)' == 'X64'" SourceFiles="$(MSBuildProjectDirectory)\Resources\x64\FreeImage.dll" DestinationFolder="$(TargetDir)" />
  </Target>

答案 1 :(得分:1)

在这种情况下,您可能希望使用像MSBuild这样的东西来控制构建。然后你可以使用编译标志来进行32位或64位编译。通过这样做,它还可以让你控制你推动的dll。这听起来像是你最好的选择。如果你不喜欢msbuild,你也可以使用nant。

答案 2 :(得分:1)

另一个选择是在Visual Studio中创建一个新的配置,除了Debug和Release ....可能是Debug32和Debug64等。其中一个配置设置是CPU架构。

然后在Project的post构建事件中,您可以使用平台名称宏作为条件来执行旧式if / else语句...

或者如果您使用平台名称作为解决方案中存储非托管dll的子目录,您可以使用平台名称从目录复制到bin目录。

答案 3 :(得分:1)

我们一直在处理这个项目。

我们有一个具有32位和64位版本的非托管C ++ DLL,以及一个使用P / Invoke调用非托管DLL的C#项目。

对于C ++ DLL,它的目标路径是:

$(PlatformName)\ $(ConfigurationName)\ $的TargetName)

因此,32位版本将在Win32 \ Release中发布,而64位调试版本将在x64 \ Debug中进行。

在C#项目中,我们删除了“Any CPU”配置,并将其替换为新的“x86”配置和“x64”配置。它的输出目录类似于非托管C ++ DLL,除了.NET编译器使用'x86',而C ++使用'Win32'来表示32位架构可执行文件。

在C#项目的构建后步骤中,我们将适当的非托管DLL复制到C#可执行文件的目标目录中。由于C#项目的每个体系结构和每个配置都有一个单独的输出目录,因此可以毫不费力地保持非托管DLL的哪个体系结构位于哪个输出目录中;他们总是匹配。

为了进一步简化这一点,我建议您研究构建一个多文件程序集(http://msdn.microsoft.com/en-us/library/226t7yxe.aspx),这样您的非托管DLL及其C#包装器都可以驻留在单个.NET程序集中,从而避免了复制它的麻烦一点都不。

答案 4 :(得分:0)

如果将配置设置为具有两个平台,一个用于32位和64位版本。然后将每个平台的引用设置为正确的dll版本,然后您需要做的就是在引用属性上设置copy local标志,而vsts将为您处理所有这些。没有麻烦没事。