by Brian Ensink
20. October 2009 21:58
Yipes! Don't ever accidentally click "Unshelve" a shelf set in TFS containing code you already checked in weeks ago. I wanted to delete an old shelf set but absent mindedly unshelved it instead, I even cancelled it half way through but the damage was already done. This completely hid the fact that I had already checked in those files. TFS showed the unshelved files as "Added" or "Edited" making me doubt whether I ever checked them in weeks ago. Only after confirming with another coworker whose TFS was not obscured with my shelf set did I trust that I had in fact checked in those files weeks ago and not made some other brain dead mistake. As penance I got to spend the next half hour or so undoing checkouts, getting latest, merging conflicts, overwriting readonly files, again and again, file by file, and gently reassuring TFS that I was not intentionally trying to violate the space-time continuum. So the moral of the story is don't accidently unshelve ancient code! Click with care.
by Brian Ensink
5. October 2009 23:17
In a previous post I pointed out some resources to help write PInvoke signatures to call platform functions from C# or VB.NET code. This type of interop can also be used to introduce C#/VB.NET code to an application not using the .NET Framework. For example perhaps a new GUI can be written in C# that reads and writes data using an existing C++ database layer. This form of interop is useful if you:
- Need to call unmanaged code from C# or VB.NET
- Have control over the unmanaged C/C++ codebase
- Don’t have or don’t want to use a COM interface
- Can reduce your module’s interface to C functions (PInvoke provides limited object oriented support, essentially whatever you can do with structs and no classes)
Below is very well near the simplest possible example.
First create a Win32 DLL project in Visual Studio and add the code below, a single trivial function. The “__declspec(dllexport)” exports the function from the DLL allowing outside modules to call it and the “extern “C”” prevents C++ name mangling.
1: extern "C" __declspec(dllexport) int Add(int a, int b)
2: {
3: return a + b;
4: }
Next create a C# project (or VB.NET if you prefer). If you are already experienced with platform-invoking Windows functions this code will be familiar. Lines 8 and 9 import the function from the DLL created above. See my previous post linked above for more resources on PInvoke signatures.
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: Console.WriteLine(Add(10, 20));
6: }
7:
8: [DllImport("My_CPP_Project.dll")]
9: static extern int Add(int a, int b);
10: }
To run the code both the DLL from the first step and the EXE from the second step must be in the same folder. However its possible to dynamically load the unmanaged DLL from a different folder using LoadLibrary from the C# EXE. Simply ensure that you call LoadLibrary to correctly load the DLL before making any calls to the functions exported by the DLL.