7
votes

We are creating a C# wrapper around a unmanaged DLL. The unmanaged DLL comes in both a 32 and 64bit versions. We keep the managed wrapper in its own project so that we can build it as a separate component and reuse it across solutions.

However this leads to some problems. Since the unmanaged DLL has the same name for both the 32bit and 64bit versions we are having trouble moving the correct unmanaged DLL to the output (bin) directory. If the build configuration is x86 we want to copy the 32bit version and with x64 the 64bit. With just one processor architecture this is easy to achieve. We just include the unmanaged DLL in our project and set copy local to true on the file. But since we need to target both its more tricky.

We found this link Targeting both 32bit and 64bit with Visual Studio in same solution/project but this seems to reference some DLL that already exist on the machine. We want the correct version of the DLL to be copied to the output directory (bin).

Any tips or techniques on how to solve this are more than welcome.

5

5 Answers

5
votes

I just went through this same issue with the .Net wrapper for the FreeImage library. What I did was create two build configurations, one for x86 and one for x64 for the project that references the managed wrapper. I added msbuild conditional copy sections in the AfterBuild target of the project file like so:

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

You might want to look into using something like MSBuild to control your builds in this case. Then you could have a compile flag you use to do the 32 or 64 bit compile. By doing this it would also allow you to control which dll you push. This sounds like your best option. If you don't like msbuild you could also use nant.

1
votes

One other option would be to create a new Configuration in Visual Studio besides Debug and Release.... perhaps Debug32 and Debug64, etc. One of the configuration settings is the CPU architecture.

Then in your Project's post build events, you can do an old fashioned if/else statement using the platform name macro as the condition...

Or if you used the Platform Name as the subdirectory in your solution where the unmanaged dll was stored, you could copy from the directory using the platform name to the bin directory.

1
votes

We deal with this all the time with our projects.

We have an unmanaged C++ DLL that has 32- and 64-bit versions, and a C# project that uses P/Invoke to call into the unmanaged DLL.

For the C++ DLL, it's Target Path is:

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

So the 32-bit release build would go in Win32\Release, and the 64-bit debug build would go in x64\Debug.

In the C# project we delete the 'Any CPU' configuration, and replace it with a new 'x86' configuration and a 'x64' configuration. Its output directories are similar to the unmanaged C++ DLL's, except that the .NET compiler uses 'x86' whereas C++ uses 'Win32' to denote a 32-bit architecture executable.

In the post-build step for the C# project we copy the appropriate unmanaged DLL into the target directory for the C# executable. Since each architecture and each configuration of the C# project has a separate output directory, there's no problem keeping straight which architecture of the unmanaged DLL is in which output directory; they always match.

To simplify this further I suggest you investigate building a multi-file assembly (http://msdn.microsoft.com/en-us/library/226t7yxe.aspx) so your unmanaged DLL and its C# wrapper can both reside in a single .NET assembly, saving you the hassle of copying it around at all.

0
votes

If you set your configuration to have two platforms, one for the 32 bit and 64 bit versions. Then you set the reference for each of the platforms to the correct dll version then all you need to do is set the copy local flag on your references properties and vsts will handle it all for you. No muss no fuss.