Locating the NuGet 3 package cache

With the new NuGet version included with Visual Studio 2015 there have been major changes in its UI and functionality, and one of the seems to be an overly aggressive cache that is the first preference when fetching package versions.

This is problematic if you are creating a new NuGet package and want to test a quick series of changes but don’t want to upgrade its version number; the cached package will be fetched always even if your package source is set to a local folder.

While on the old versions of NuGet it sits in %LOCALAPPDATA%\NuGet\Cache, from NuGet 3 onwards the new cache location is in %USERPROFILE%\.nuget\packages, and each package has its own folder, containing one subfolder for each version. When deleted from here, a fetch of the original package source will be forced.

How to compile a static library as a DLL using VC++

So you have the source code for an old, static library lying around and you want to compile it as a dynamically linked one for whatever reason. Well, it’s as easy as going to the project properties > Configuration Properties > General and change Configuration Type to Dynamic Link Library (.dll).

image

See? Now you can hit F6 and have VC++ compile it into your new, shiny DLL. Grab it from the output directory, link it at your pleasure and start usi- wait, it doesn’t work.

If you examine the DLL with a tool like dumpbin.exe and ask it to show you the exported symbols, you will see something like this:

image

What does this mean? Yes, your DLL is still full of code, like function and class definitions, but not a single one of them is being exported. How can we solve it? Navigate to the header files and stick a __declspec(dllexport) before each function/variable/class definition you want to export. Now recompile and watch magic happen:

image

Now your DLL has the necessary info for linking. And if you are going to import it via GetProcAddress/DllImport, you are good to go. But if you want to do things the best way, continue reading.

Okay, so our library now exports symbols via the header files, and to use it, you must load it at runtime, get the handle to the function pointers… We can alleviate the programmer’s task by defining a small macro in the root header:

    1 #ifndef EXPORTS

    2 #define DECLSPEC_ACTION __declspec(dllimport)

    3 #else

    4 #define DECLSPEC_ACTION __declspec(dllexport)

    5 #endif

and changing all our previous __declspec(dllexport) with the new DECLSPEC_ACTION macro. In the DLL project, go to project properties > Configuration Properties > C/C++ > Preprocessor and add the EXPORTS keyword to the Preprocessor Definitions field. Now you can distribute your compiled DLL along with the header files containing all your definitions, and the compiler will know that it can ignore the missing function bodies because they are implemented in a external library that will be resolved at runtime.

Finally, maybe you are wondering why the function names shown by dumpbin.exe are so funny. They are called decorated names, and each compiler has its own way of generating them. Why are they so strange? Because C++ has some features like classes and operator overloading, and standard C used to name functions only by their name, without taking into account their parameters (and that’s why you can’t have two functions with the same name); this way the compiler can generate unique names that will be correctly resolved when linking.

So, if you want to have your perfectly enginereed DLL, rewrite all your function definitions so there aren’t two of them with the same name, and put an extern “C” when defining them. When compiled, the DLL will be generated with standard C symbols and you will ensure that it will work the same across ALL compilers and platforms, and will make the use of GetProcAddress/DllImport easier:

image

That’s it. Now you have successfully created a DLL from a static library that can be called from standard C/C++ code via the header files or loaded at runtime. What’s coming next? Creating a managed wrapper for it, so stay tuned!