6

I've read many questions and answers indicating that if I want to link my C# project against native libraries, I can't use AnyCPU platform target but must make separate 32- and 64-bit builds, each linked against the native DLL of the appropriate bitness.

This makes me wonder how the .NET Framework assemblies themselves are, or at least appear to be, built for AnyCPU. That is, when adding a reference to my GUI application, why don't I have to pick the 32-bit or 64-bit version of System.Windows.Forms? I thought this might just be some Visual Studio magic that would resolve to the appropriate GAC subdirectory (GAC_32 or GAC_64), but I searched for System.Windows.Forms.dll in the GAC and found it in:

C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll

Note the "GAC_MSIL". So how does this DLL manage to wrap a native 32-bit API yet remain linkable in a 64-bit application? And why can't I use a similar strategy to make a single C# DLL that links against a native 32-bit library yet remains runnable in 64-bit mode?

adv12
  • 8,443
  • 2
  • 24
  • 48
  • It is because .NET assemblies aren't compiled down to processor instructions. They compile down to an [intermediate language](https://en.wikipedia.org/wiki/Common_Intermediate_Language), which then runs through the .NET framework and is translated to processor instructions at runtime. – pquest Jan 25 '16 at 19:30
  • @pquest, I think I understand that much but don't quite see how it answers my question. Can you elaborate? – adv12 Jan 25 '16 at 19:31
  • Just load the correct version of the native dll before calling any api? That's how most of the assemblies which does native interop works. – Sriram Sakthivel Jan 25 '16 at 19:37
  • without ever having looked, I would imagine that things that wrap the native API like that probably check which mode an application is in at runtime and import the proper DLL. [This answer](http://stackoverflow.com/questions/10852634/using-a-32bit-or-64bit-dll-in-c-sharp-dllimport) has an example of someone doing just that. – pquest Jan 25 '16 at 19:37
  • So from the comments here and what I've read in linked questions, it begins to sound like this is doable with P/Invoke but not with C++/CLI, which is the route I took for wrapping the native libraries. Thanks all for the input; I'll keep reading... – adv12 Jan 25 '16 at 19:47

2 Answers2

0

Option 1: In GAC you may register 2 versions of assembly one 32 and one 64 bit with exactly same names. Oracle DB Driver for .NET uses this strategy.

Option 2: With your assembly that will be AnyCPU deploy two versions of native DLL and choose proper DLL at runtime (SQLite works like that). As it turns out .NET Framework is intelligent enough to load proper version of native DLL via P/Invoke (Using a 32bit or 64bit dll in C# DllImport)

Community
  • 1
  • 1
csharpfolk
  • 4,124
  • 25
  • 31
0

I had the same problem and ended up using Fody Costura

DLL Files will be shipped as embedded ressources and the lib takes care of the bitness.

You could find an example for SQLite here

The problem I have encountered was that your application needs to have access to the Windows Temp folder to create the assemblies from the ressource. If you dont need it, you could disable it using a config setting createtemporaryassemblies

Manfred Wippel
  • 1,946
  • 1
  • 15
  • 14