views:

1122

answers:

7

Hi there,

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 http://stackoverflow.com/questions/145803/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.

+1  A: 

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.

Joshua Cauble
+1  A: 

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.

Nick
A: 

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.

Alex
+3  A: 

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>
duckworth
Hi and thanks for the reply. We've implemented the afterbuild target as you suggested in the project file of the wrapper project. However, from other projects that is referencing the wrapper project the unmanaged DLL are not copied into into the bin directory together with the wrapper DLL. Any tips on how to achieve this?
flalar
Generally, what we do for all indirectly referenced and/or dynamically loaded assemblies is push them from their projects TargetDir to a common output folder with a post build command. Then any projects that need them copy them to their TargetDir with a pre/post build command as well.example push:xcopy "$(TargetDir)$(TargetFileName)" "$(SolutionDir)PluginOutput\" /E/Yexample pull:xcopy "$(SolutionDir)PluginOutput\*.dll" "$(TargetDir)" /E/Y
duckworth
+1  A: 

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.

anelson
So a multi-file assembly would pretty much be a C# assembly that contains both x86 and x64 unmanaged dll and loads the appropriate one?
flalar
Not exactly.Say you have ManagedAssembly.dll, written in C#, and both 32- and 64-bit versions of NativeAssembly.dll in C++.You could create two multi-file assemblies, one with ManagedAssembly.dll and the 32-bit NativeAssembly.dll, and another with ManagedAssembly.dll and the 64-bit NativeAssembly.dll. This way you only have to worry about the one DLL dependency instead of a mix of architecture-agnostic and architecture-specific DLLs.
anelson
A: 

Where did you get the x64 version of FreeImage DLL? I've been looking for it for some time, but one doesn't seam do exist!

sansegot
A: 

@sansegot: the x64 version of freeimage doesn't exists, you have to built it by yourself,

http://www.sambeauvois.be/blog/2010/05/freeimage-and-x64-projects-yes-you-can/

Sam