Archive for the ‘c#’ Category

c# new vs. override

Monday, July 26th, 2010

C# has two keywords for decorating methods, new and override, that have almost identical effects. Almost. They are both used to override a method on a base class, but how do they differ? A lot of documentation I’ve read is pretty vague, saying something like, “Overriding a virtual method with the new keyword hides, rather than overrides, the base class implementation of the method.” Here is what that means:

The override keyword creates a true run-time method override, whereas the new keyword affects only compile-time method identification. This is a bit like the difference between overriding and overloading. So if your object is declared as Animal but you’ve really got a Dog, calling a method with override will execute the Dog implementation, but calling a method with new will execute the Animal implementation, because that’s all the compiler can see.

If you have a C++ background, you can think of this in terms of a virtual method table or dispatch table. In C#, only methods marked virtual get such a table. The override keyword adds a new entry to that table, whereas new does not.

C# is more conservative than Java when it comes to method overrides. In Java, by default you can override any method, after accounting for the usual access modifiers (public/protected/private). This led to problems where subclasses could break functionality by overriding methods the base class didn’t expect. In C#, you can only override those methods the base class explicitly permits. So you can only use override if the base class method is marked virtual. However, you can use new on any method. As long as the compile-time type of an object is the subclass, your new method will be called, but the base method will continue to be called elsewhere, including (most importantly) from within the base class.

A Linq Catalog

Tuesday, March 16th, 2010

I thought I’d review the special methods available in Linq. In the API reference, they can be found under the Enumerable<T> class. Here they are:


static IEnumerable<T> Empty<T>()
static IEnumerable<T> Repeat<T>(T element, int count)

T[] ToArray()
List<T> ToList()
Dictionary<K,T> ToDictionary(Func<T,K> keySelector)    // puts every element in a dictionary
                                                       // using keys generated by keySelector
Dictionary<K,T> ToDictionary(Func<T,K> keySelector, IEqualityComparer<K>)
Dictionary<K,R> ToDictionary(Func<T,K> keySelector, Func<T,R> elemSelector)
                               // transforms each T to an R and puts the Rs in the dictionary
Dictionary<K,R> ToDictionary(Func<T,K> keySelector, Func<T,R> elemSelector, IEqualityComparer<K>)
Lookup<K,T> ToLookup(Func<T,K> keySelector)           // a Lookup is like a Dictionary except
                                                      // each key points to a list of values.
                                                      // In Perl terms it's a hash of arrays.
Lookup<K,T> ToLookup(Func<T,K> keySelector, IEqualityComparer<K>)
Lookup<K,R> ToLookup(Func<T,K> keySelector, Func<T,R> elemSelector)
Lookup<K,R> ToLookup(Func<T,K> keySelector, Func<T,R> elemSelector, IEqualityComparer<K>)

T Aggregate(Func<T,T,T> adder)        // like python's reduce

T ElementAt(int index)
T ElementAtOrDefault(int index)       // returns this[i] or default(T) if i >= this.Count

T First()
T First(Func<T,Boolean>)              // the first element that satisfies the predicate
T FirstOrDefault()
T FirstOrDefault(Func<T,Boolean>)
T Last()
T Last(Func<T,Boolean>)               // the last element that satisfies the predicate
T LastOrDefault()
T LastOrDefault(Func<T,Boolean>)

T Single()                        // returns the only element of the sequence,
                                  // or throws an exception
T Single(Func<T,Boolean> f)       // returns the only element for which f returns true.
                                  // Exception if there is not one and only one.
T SingleOrDefault()               // default(T) if empty. Still exception if more than one T.
T SingleOrDefault(Func<T,Boolean> f)

bool Contains(T)
bool Contains(T, IEqualityComparer<T>)
bool All(Func<T, bool> predicate)       // true if predicate is always true
bool Any(Func<T, bool> predicate)       // true if predicate is ever true
bool Any()                              // true if the sequence contains any elements
bool SequenceEqual(IEnumerable<T>)      // true if all the elements of the two sequences
                                        // are equal, using T's default equality comparer.
bool SequenceEqual(IEnumerable<T>, IEqualityComparer<T>)

int Count()
int Count(Func<T,Boolean>)    // counts how many elements satisfy the predicate.
long LongCount()
long LongCount(Func<T,Boolean>)

int Average()
int Average(Func<T,int> transform)    // calls transform to alter each element before
                                      // including it in the average.
                                      // You could use this to get a weighted average, e.g.
int Max()
int Max(Func<T,int> transform)        // uses transform to turn each T into an int
int Min()
int Min(Func<T,int> transform)
int Sum()
int Sum(Func<T,int> transform)
// ... lots of overloads ...

IEnumerable<T> DefaultIfEmpty()          // returns [default(T)] if empty
IEnumerable<T> DefaultIfEmpty(T elem)    // returns [elem] if empty.

IEnumerable<T> AsEnumerable()    // forces the compiler to call IEnumerable<T> methods
IEnumerable<R> Cast<R>()         // casts each element to an R
IEnumerable<R> OfType<R>()       // filters out any elements not of type R

IEnumerable<T> Intersect(IEnumerable<T> compare)    // the standard set operation
IEnumerable<T> Intersect(IEnumerable<T> compare, IEqualityComparer<T>)
IEnumerable<T> Union(IEnumerable<T> compare)        // the standard set operation
IEnumerable<T> Union(IEnumerable<T> compare, IEqualityComparer<T>)
IEnumerable<T> Except(IEnumerable<T> compare)       // returns this - compare
IEnumerable<T> Except(IEnumerable<T> compare, IEqualiterComperer<T>)

IEnumerable<T> Distinct()                      // like SQL distinct keyword
IEnumerable<T> Distinct(IEqualityComperer<T>)
IEnumerable<T> Concat(IEnumerable<T>)          // like Union, but with list semantics
                                               // instead of set
IEnumerable<T> Range(int start, int count)

IEnumerable<T> Skip(int n)                       // skips n elements; returns the rest
IEnumerable<T> SkipWhile(Func<T,Boolean> f)      // skips while f is true; returns the rest
IEnumerable<T> SkipWhile(Func<T,int,Boolean> f)  // f also gets the 0-based index
IEnumerable<T> Take(int n)                       // returns Range(0,n)
IEnumerable<T> TakeWhile(Func<T,Boolean> f)      // takes while f is true; skips the rest
IEnumerable<T> TakeWhile(Func<T,int,Boolean> f)

IEnumerable<T> While(Func<T,Boolean> f)     // gets the elements where f is true.
IEnumerable<T> While(Func<T,int,Boolean> f) // f also knows the 0-based index.

IEnumerable<IGrouping<K,T>> GroupBy(Func<T,K> f)    // f generates a key for each element
IEnumerable<IGrouping<K,R>> GroupBy(Func<T,K> f, Func<K, IEnumerable<T>, R> resultSelector)
                       // resultSelector gets an enumeration of values with a given key,
                       // and it returns a single value of type R, e.g. representing
                       // their min value. Note that you could use anonymous classes
                       // to stick several values into R, e.g. a min, max, and average.
                       // There is a nice example here:
                       // http://msdn.microsoft.com/en-us/library/bb549393.aspx.
... lots more overloads ...

IOrderedEnumerable<T> OrderBy(Func<T,K> keySelector)    // orders the elements based on keys
                                                        // generated by keySelector
IOrderedEnumerable<T> OrderBy(Func<T,K> keySelector, IComparer<K> comp)
                                // orders the elements based on keys generated by keySelector
                                // and compared by comp
IOrderedEnumerable<T> OrderByDescending(Func<T,K> keySelector)
IOrderedEnumerable<T> OrderByDescending(Func<T,K> keySelector, IComparer<K> comp)
IEnumerable<T> Reverse()
IOrderedEnumerable<T> ThenBy(Func<T,K> keySelector)     // sub-sorts elements deemed equal
                                                        // by a previous sort
IOrderedEnumerable<T> ThenBy(Func<T,K> keySelector, IComparer<K> comp)
IOrderedEnumerable<T> ThenByDescending(Func<T,K> keySelector)
IOrderedEnumerable<T> ThenByDescending(Func<T,K> keySelector, IComparer<K> comp)

IEnumerable<T> Join(IEnumerable<I> inner, Func<O,K> outerKeySelector,
        Func<I,K> innerKeySelector, Func<O,I,R> resultSelector)
                // joins two sequences as an inner equijoin.
                // There is no method for outer joins,
                // but GroupJoin can get used to get that effect.
IEnumerable<O,I,K,R> GroupJoin(IEnumerable<I> inner, Func<O,K> outerKeySelector,
        Func<I,K> innerKeySelector, Func<O, IEnumerable<I>, R> resultSelector)
                // joins the two sequences (see Join) and groups the results (see GroupBy).
                // Unlike with Join, this function can be used to do a left outer join,
                // because even when there is no value in inner matching a value in outer,
                // the resultSelector gets called for each outer value,
                // just with an empty IEnuemrable<I>.

IEnumerable<R> Select(Func<T,R> f)                  // uses f to transform each T to an R
IEnumerable<R> Select(Func<T,int,R> f)              // f also knows the 0-based index of each T
IEnumerable<R> SelectMany(Func<T,IEnumerable<R> f)  // f can return many Rs. All the Rs
                                                    // are flattened into one sequence.
IEnumerable<R> SelectMany(Func<T,int,IEnumerable<R> f)
IEnumerable<R> SelectMany(Func<T,IEnumerable<U> f, Func<T,U,R> g)
                // f generates an intermediate value of type U; g uses both a T and U
                // to get an R. This is really only useful if U doesn't have access to T.
                // See the example code here:
                // http://msdn.microsoft.com/en-us/library/bb534631.aspx.
IEnumerable<R> SelectMany(Func<T,int,IEnumerable<U> f, Func<T,U,R> g)

Equals and compareTo in Subclasses

Monday, March 15th, 2010

The other day I read this interesting paper on contructing a correct equals method when subclassing. It is about Java, but it applies equally well to C#. They cite Josh Bloch’s book Effective Java, who writes:

There is no way to extend an instantiable class and add a value component while preserving the equals contract, unless you are willing to forgo the benefits of object-oriented abstraction.

I read this book a while back—maybe six or seven years ago now. At the time I thought it was invaluable. It seemed like the Java version of Expert C Programming: Deep C Secrets (the fish book). But when I think back on it now, all I can remember is the author’s ongoing struggle to overcome Java’s limitations and contradictions. It seemed he was constantly recommending more and more verbose code to get around problems in the underlying language. I guess that’s not Bloch’s fault, but Java just seems to be like that. It’s the reason my resume has a crowded half-page of Java TLAs.

Anyway, contrary to Bloch’s commonly-accepted denial, the authors of the paper present a way to write an equals method that preserves the contract of equals even when extending from another non-abstract class and adding more state. Their solution isn’t even that verbose or twisted. It’s worth a read. Basically they recommend this (some parts changed for brevity):


public class Point {
    public int x;
    public int y;

    public boolean equals(Object other) {
        boolean result = false;
        if (other instanceof Point) {
            Point that = (Point)other;
            result = that.canEqual(this) && this.x == that.x && this.y == that.y;
        }
        return result;
    }

    public boolean canEqual(Object other) {
        return (other instanceof Point);
    }

    public int hashCode() {
        return 41 * (41 + x) + y;
    }
}

public class ColoredPoint extends Point {
    public Color color;

    public boolean equals(Object other) {
        boolean result = false;
        if (other instanceof ColoredPoint) {
            ColoredPoint that = (ColoredPoint)other;
            result = that.canEqual(this) && color.equals(that.color) && super.equals(that);
        }
        return result;
    }

    public boolean canEqual(Object other) {
        return (other instanceof ColoredPoint);
    }

    public int hashCode() {
        return 41 * super.hashCode() + color.hashCode();
    }
}

The trick here is that canEquals method. It is not really a public method; it is only called from within the equals method. But note that an object doesn’t call it’s own canEquals method; it calls it on the other object. This lets the two objects agree that they are really equal, and it solves the problem of non-symmetric implementations of equals (where a.equals(b) != b.equals(a)). This is a common problem, because a Point might think it equals a ColoredPoint, whereas the ColoredPoint knows it doesn’t equal the Point.

The naive way of ensuring symmetry would be to replace instanceof with a comparison of the object’s actual class. But this is too crude, because it means you can’t use anonymous classes. For instance, a Point should still equal an anonymous class instance like this one:


Point pAnon = new Point() {
    public void overrideSomeMethod() {
        // ...
    }
}

With canEquals, the anonymous class simple inherits canEquals from Point, and the two objects will still agree on their equality. I think this is a really nice solution to a thorny problem.

The forum discussion about the paper (which is almost as good as the paper itself) argues that Java ought to support an Equalator interface as a parallel to Comparator<T>. The idea is that just as you can override the “natural ordering” of a class, you should be able to override its “natural equivalence.” This would let you instantiate a Set, HashMap, etc. with an Equalator to get a different notion of equals than usual. Just as objects may sort differently in different contexts, so they may “be equal” differently in different contexts, depending on what you care about. Who hasn’t run into the need for a Set based on reference identity, for example? Apache Collections provides just such a class.

The need for an Equalator seems most pressing in classes like TreeSet that use compareTo rather than equals to test for set duplicates. If you use a TreeSet with a Comparator that is not consistent with equals, that the TreeSet will appear to violate the set contract, because you could have a.equals(b) but s.contains(a) != s.contains(b). I went to bed thinking it’s a shame Sun hasn’t added this Equalator concept.

But as I was thinking about it over the night, I started to believe Sun is right to leave it out, at least in so far as it pertains to classes like TreeSet that use compareTo instead of equals. Basically, the TreeSet’s Comparator is already operating as an Equalator here. Why do you need an Equalator, too? What problem would it solve that isn’t already solved by the Comparator? If you passed an Equalator to a TreeSet, it wouldn’t change this code problem: a.equals(b) && (s.contains(a) != s.contains(b)). The whole point of an Equalator is to impose a different notion of equality on a limited context, and with TreeSet a Comparator is sufficient for that.

Of course, that’s not to say an Equalator wouldn’t be useful in a regular Set or Map. It turns out that C# does have the Equalator idea, but it’s called IEqualityComparer<T>. It doesn’t seem to be used much, but Dictionary<K,V> and HashSet<T> both support it.

I actually came across this paper while thinking about how C#’s CompareTo<T> can work in a class heirarchy. As in Java, this method must be “consistent with Equals.” That is, whenever Equals returns true, CompareTo must return 0, and whenever CompareTo returns 0, Equals must return true. Put into code, (a.CompareTo(b) == 0) == a.Equals(b). The CompareTo method is tricky because it’s parameterized: its signature is bool CompareTo(T o), where T comes from IComparable<T>.

So what happens if you have Base : IComparable<Base> and Subclass : Base, IComparable<Subclass>? My instinct is you’re asking for trouble, although when I think it through it seems that the compiler will choose the method based on the current static type, not the instance’s actual type, so maybe you’d be okay. If your code is interested in comparing Bases, you’ll call that method; you’ll only call CompareTo(Subclass o) if you’re explicitly comparing Subclasses. So maybe everything will work out, but I’m still uneasy.

I also see that C# 4.0 is supporting new keywords for co- and contra-variance in generic parameters. So we get IEnumerable<out T> and IComparable<in T>. This means that if you implement IEnumerator<Subclass> GetEnumerator, you also fulfill the contract for IEnumerable<Base>, and if you implement CompareTo(Base o), your subclass doesn’t have to implement CompareTo(Subclass o) in order to fulfill the contract for IComparable<Subclass>. I hope I’ve got that right!

The first part—covariant return types—seems like the bigger deal here. (I only wish it were full covariant return types as in C++!) But the part about IComparable seems nice, too. It should save a bit of code, because it means that if you have a full-featured base class and you want to write a quick subclass on top of it, you can still use your subclass in things that require an IComparable<Subclass> (like List<Subclass>) without writing another CompareTo implementation.

Viewing Unit Test Output in Visual Studio

Thursday, March 11th, 2010

I’ve been using Visual Studio 2008 to write unit tests. I had a couple failing in very strange ways, and I wanted to add some debugging statements to watch the state of the code. I usually find this more useful than running a debugger. (If that seems weak, then I’ll just say that K & R agrees with me!) I can print whatever state I want and I don’t have to deal with breakpoints. Furthermore, once those debugging messages are in there, I can leave them there so they help out next time.

The problem was that I couldn’t figure out how to see Console output for unit tests. I kept trying to open various Output windows: Build output, Debug output, Refactor output. No Test output! Googling didn’t turn up anything. Today I was hitting the same problem, so I thought I’d try Googling one more time. I must have hit the magic search term combination, because this time all my top results were relevant.

It turns out to see a test’s output, you just double-click on the test summary line, and all the output is down at the bottom of that window. You get Console.Out messages and (more importantly) {Trace,Debug}.WriteLine(). Wonderful!

C# XmlTextReader Tutorial

Saturday, February 27th, 2010

I needed to read a big XML file into an object structure. I wanted it to be fast and use a low memory footprint. I also wanted the XML to stay pretty clean to make future support easy. Because of the speed and memory requirements, DOM and XPath were out. I toyed around with XmlSerializer, but it didn’t quite give me the XML I wanted—too ugly—and I didn’t like cluttering my classes with xml serialization attributes. That doesn’t belong in the objects, does it? And then the code to structure the XML is scattered around everywhere. And finally, what if I need to serialize the objects in different ways at different times?

So I thought I’d try my hand at XmlTextReader, which is a bit like SAX but more “push” than “pull.” It’s not based on callbacks, and you don’t have to manage state so attentively. Coming from the Java world, I’m used to SAX. I actually like it. The state machine thing isn’t so hard, really. So I was pretty excited about XmlTextReader. It looked like it would have the advantages of SAX but be easier to use.

Having now written some code with XmlTextReader, I’m still pretty happy with it, but I’m a bit disappointed that Microsoft junked up the API so much. It seems gappy and needlessly complicated. But having learned it, I thought I’d set it all down in writing.

One approach, which is fairly SAX-like, is to put everything into a read loop and switch on element names. That might look like this:


XmlTextReader r = new XmlTextReader(stream);
r.WhiteSpaceHandling = WhiteSpaceHandling.None;
while (r.Read()) {
  if (r.NodeType.Equals(XmlNodeType.Element)) {
    switch (r.LocalName) {
	  case "this":
	    // processing ...
		break;
      case "that":
	    // processing ...
		break;
	  // more cases ...
	}
  }
}

If you wanted, you could stop there. The Read() method gives you one node at a time, and you handle each element. You could add code to handle endElements also, or comments, or whatever, just as in SAX. But there are lots of other methods to make things easier.

If you’ve never done this sort of thing before, you should know that an XML document consists of nodes. A node can be a start element, an end element, a run of text, a comment, a processing instruction, even whitespace. By setting WhitespaceHandling to None above, we told the XmlTextReader to skip whitespace, so Read() doesn’t report it. Attributes are nodes too, but the Read loop doesn’t emit them, either. Instead you use special methods to get at attributes when you’re positioned on their containing element. As you can see, some nodes have children (e.g. some elements), whereas other nodes are leaves (text, attributes, other elements).

One tricky thing is to keep track of your current position in the document. In describing the various methods below, I’ll try to pay attention to how they affect the document position. The Read() element advances one node.

First let’s talk about some methods that look useful but you should probably avoid. One is ReadElementString(). This advances one element and returns the contents of the next element as a string. A variant is ReadElementString(elemName), which verifies that the current element matches the given name. I didn’t find these methods too useful. The first gives you no checking to see if you’re actually reading the right thing. The second checks the wrong thing. I don’t want to test the current element and then read the contents of the next one. The test needs to be the name of the next element. Both of these methods read the element blindly; the latter just looks backwards a bit.

Another method to avoid is ReadString(). This returns a string when positioned on either an element or a text node. That’s handy, but it doesn’t skip comments and processing instructions very well. For that we’ll need a different method.

One method that looks great is MoveToElement(elemName). But if you think this will scan through the document until it finds your desired element, you’re wrong. Instead, this is used in attribute processing to move up from the attributes back to their owning element. Alas!

One method that really is handy is MoveToContent. This skips over comments, whitespace, processing instructions, and documentType nodes. In all your processing, you should be aware that users may throw comments into weird places. Robust XML parsing doesn’t get tripped up by comments. So this call is quite useful.

To get the contents of an element, ignoring any comments, you want the ReadContentAsXXX() methods and the ReadElementContentAsXXX() methods. These methods skip comments and processing instructions and automatically convert entities. This is just the sort of friendly assistance you want from your XML parser. As for the XXX, you have a lot of options. It could be String, Int, DateTime, even Object.

The difference between ReadConentAs and ReadElementContentAs is this: the first must be positioned on a text node, whereas the latter can be positioned on either a text node or the text’s containing element. If you call ReadContentAs on an element, you get an exception. In practice, I think ReadElementContentAs is the more useful family of methods. Also, when it returns, the reader is positioned at whatever follows the endElement node of what you just read. If you’re ignoring whitespace, this could be the next element. (Or it could be a comment, etc.)

Then there are a few methods for moving around in the document. I think this is where the API really falls short, but here’s what we’ve got: ReadToFollowing, ReadToNextSibling, and ReadToDescendant. All these methods take an element name and return true if it is found, leaving you positioned on the element node (and ready to call ReadElementContentAs). If they can’t find what you want, they return false, and then your new position in the document is however far they’ve searched. You’ll be at EOF for ReadToFollowing, or the end tag of the current/parent element for the other two. This is a bit of a disappointment. If you’re looking for a required element, you could just throw an exception, but what about finding optional elements? It’s no big deal the element wasn’t there, but you’re way off course.

One other useful method is Skip(). This skips the children of the current node.

Here is some code making use of these elements to parse a fairly simply document. The document describes a family, with elements for headOfHousehold, spouse, and children. Each person has a name, birthdate, and sex. Let’s treat the last two of these as optional. The spouse node can also have an optional marriageDate element. We could indicate the XML structure like this, where wildcards have their usual meaning (? = 0 or 1, * = 0 or more, + = 1 or more):


family
  headOfHousehold
    name
      birthdate?
      sex?
  spouse?
    name
    birthdate?
    sex?
    marriageDate?
  children?
    child+
      name
      birthdate?
      sex?

Here is some code that processes such a file by building up an object structure, then prints the results:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace XmlTextReaderTest {

    public enum Sex { MALE, FEMALE }

    public class Person {
        public string Name { get; set; }
        public DateTime Birthdate { get; set; }
        public Sex Sex { get; set; }
        public DateTime? MarriageDate { get; set; }

        public override string ToString() {
            return String.Format("{0}: {1}, {2:yyyy-MM-dd}, {3:yyyy-MM-dd}", Name, Sex, Birthdate, MarriageDate);
        }
    }

    public class Family {
        public Person Head { get; set; }
        public Person Spouse { get; set; }
        public List<Person> Children { get; private set; }

        public Family() {
            Children = new List<Person>();
        }

        public override String ToString() {
            String ret = "Head:\n\t" + Head + "\nSpouse:\n\t" + Spouse + "\n";
            foreach (Person p in Children) {
                ret += "Child:\n\t" + p + "\n";
            }
            return ret;
        }
    }

    public class Program {
        static void Main(string[] args) {
            string xmlDoc = @"<?xml version='1.0' encoding='utf-8'?>
<family>
    <headOfHousehold>
      <name id='asdf'>Paul Jungwirth</name>
      <!-- not my real birthday of course: -->
      <birthdate>1975-02-08</birthdate>
      <sex>male</sex>
    </headOfHousehold>
    <spouse>
      <name>Arielle Jungwirth</name>
      <birthdate>1979-11-11</birthdate>
      <sex>female</sex>
      <marriageDate>2006-09-09</marriageDate>
    </spouse>
    <children>
      <child>
        <name>James Jungwirth</name>
        <birthdate>2007-12-31</birthdate>
        <sex>male</sex>
      </child>
      <child>
        <name>Miriam Jungwirth</name>
        <birthdate>2010-01-20</birthdate>
        <sex>female</sex>
      </child>
    </children>
</family>";
            Family f = ParseFamily(new MemoryStream(Encoding.Default.GetBytes(xmlDoc)));
            Console.Write(f);
            Console.ReadLine();
        }

        public static Family ParseFamily(Stream stream) {
            Family f = new Family();
            XmlTextReader r = new XmlTextReader(stream);
            r.WhitespaceHandling = WhitespaceHandling.None;
            r.MoveToContent();

            while (r.Read()) {
                // Console.WriteLine(r.NodeType + ": " + r.LocalName + "\n");
                if (r.NodeType.Equals(XmlNodeType.Element)) {
                    switch (r.LocalName) {
                        case "headOfHousehold":
                            f.Head = ParsePerson(r);
                            break;
                        case "spouse":
                            f.Spouse = ParsePerson(r);
                            f.Head.MarriageDate = f.Spouse.MarriageDate;
                            break;
                        case "child":
                            f.Children.Add(ParsePerson(r));
                            break;
                        default:
                            // ignore other nodes
                            break;
                    }
                }
            }

            return f;
        }

        public static Person ParsePerson(XmlTextReader r) {
            Person p = new Person();

            // Right now we're pointing to the person's containing element, e.g. headOfHousehold.
            // Read past that, then read until we get to a new start element.
            r.Read();

            r.MoveToContent();
            if (r.LocalName.Equals("name")) p.Name = r.ReadElementContentAsString();
            else throw new InvalidDataException("no name for person");

            r.MoveToContent();
            if (r.LocalName.Equals("birthdate")) p.Birthdate = r.ReadElementContentAsDateTime();

            r.MoveToContent();
            if (r.LocalName.Equals("sex")) p.Sex = (Sex)Enum.Parse(typeof(Sex), r.ReadElementContentAsString(), true);

            r.MoveToContent();
            if (r.LocalName.Equals("marriageDate")) p.MarriageDate = r.ReadElementContentAsDateTime();

            return p;
        }
    }
}

This code demonstrates on a small scale the pattern I use to parse XML documents and keep the code manageable. I read through the whole document using our Read/switch loop, and I call out to helper functions to build objects representing significant chunks. These methods may call other helper functions or (as here) just navigate through the XML to pick out primitives. Each chunk of code is self-contained, and you’re never looking at more than a page or so.

You can see that in building each Person, I use MoveToContent and then test the name of the next element. Calling ReadElementContentAs takes me past the endElement, so afterwards I’m ready to read some more. If I’m already on an element, MoveToContent won’t advance at all, so it’s safe to call twice in the case when an optional element is missing.

You could also implement ParsePerson as a second Read/switch loop. That would mean the child elements can come in any order, but you’d have to verify at the end that you got data for all the required ones. You also may not know when to exit, if the name of your endElement can vary as in this example (e.g. “spouse” vs. “child”).

Sorting Out the Confusion: 32- vs. 64-Bit, CLR vs. Native, C# vs. C++

Saturday, February 13th, 2010

I’ve been trying to learn how things work on Windows based on whether you write code in C# or C++, target a 32- or 64-bit platform, and produce files with either native code or one of the CLR options. One of my focuses is the interaction between exes and dlls. I think I’ve got things mostly straightened out, so this is what I’ve learned.

First, the basics: a 32-bit platform can run 32-bit apps, but not 64-bit apps. A 64-bit platform can run either, but 32-bit apps run in an emulation environment called WOW64 (Windows on Windows 64). When Windows starts your app, it decides whether WOW64 is necessary. You can tell whether your app is running in WOW64 using this C++ code:


#include "stdafx.h"
#include <windows.h>

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

LPFN_ISWOW64PROCESS fnIsWow64Process;

BOOL isWow64() {
    BOOL ret = FALSE;
    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
        GetModuleHandle(TEXT("kernel32")), "IsWow64Process");

    if (NULL != fnIsWow64Process) {
        if (!fnIsWow64Process(GetCurrentProcess(), &ret)) {
            printf("Got some error\n");
        }
    }
    return ret;
}

int _tmain(int argc, _TCHAR* argv[]) {
    if (isWow64()) {
        printf("Running under WOW64.\n");
    } else {
        printf("NOT running under WOW64.\n");
    }
    scanf("press return");
    return 0;
}

It’s easy enough to call isWow64 from C#, like so:


[DllImport]("IsWow64Dll.dll")]
static extern bool isWow64();

static void Main(String[] args) {
    Console.WriteLine(isWow64().ToString());
    Console.ReadLine();
}

Visual Studio lets you build files for either 32- or 64-bit platforms. I’ve already written how to build for 32 or 64 bits in C++. C# actually provides three options: 32-bits, 64-bits, or “Any CPU.” We can use a tool called corflags to see what results we get depending on which option we choose. Corflags comes with Visual Studio and can be run by choosing the special DOS prompt command under Visual Studio in the Start menu. This is a little different from the regular DOS prompt: it has a specially-tailored environment for running Visual Studio’s command-line utilities. From there, you can ask corflags to report information about any exe or dll, like this:


C:\> corflags myapp.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 3
ILONLY    : 1
32BIT     : 1
Signed    : 0

We’re mostly interested in three values: PE, 32BIT, and ILONLY. There is also a line labelled “Signed,” which I’m not interested in right now. Finally, the “CorFlags” line appears to be a combination of the four other values.

PE specifies whether or not the file can run on 32-bit platforms. It is either PE32 or PE32+. A PE32+ file cannot run on a 32-bit machine.

Next there is the 32BIT flag. This is a little different from PE. If PE indicates whether your app can run as 32 bits, then 32BIT indicates whether it must run as 32 bits. If this flag is 0, your app can run on a 64-bit machine without WOW64. But if the flag is 1, then your app has to run under WOW64. Here is a table showing how the bits are set depending on your compiler’s /platform setting:

Compiler Option PE 32BIT
x86 PE32 1
Any CPU PE32 0
x64 PE32+ 0

From this table, you can see that the corflags example above is inspecting a C# app built for the x86 platform. Note that you could never have a file that is PE32+ with the 32BIT flag set, because then one flag would require 32 bits and the other 64.

To put all this together, a 32-bit machine can run anything with a PE set to PE32, but nothing with a PE of PE32+. A 64-bit machine can run your file in 64-bit mode as long as 32BIT is 0, but if 32BIT is 1 then it must use WOW64.

The ILONLY flag indicates that your file contains only MSIL opcodes (recently renamed to CIL), with no native assembly instructions. A C# app will always have this flag set (unless you use something like ngen to compile down to machine language—an approach with some distribution problems), but a C++ app’s setting depends on your compiler options (described below).

When it comes to loading dlls, these flags control whether your app loads the dll successfully or gets a BadImageFormatException. Basically, a 32-bit app can only load 32-bit dlls, and a 64-bit app can only load 64-bit dlls. But what about apps compiled as “Any CPU”? In that case, you can only load dlls matching whatever bitness you’re currently running as. Of course, if you’re running on a 32-bit machine, there is no complication, because everything is 32-bit already.

But on a 64-bit machine, you may have problems. Windows will not use WOW64 for your app, because it claims to support 64-bit operation. But if your app has a dependency on a 32-bit dll, then you’ll get a BadImageFormatException, because the 32-bit dll only works in WOW64. The choice to use WOW64 happens only when starting your app. You can’t run an app natively and load just the dlls in WOW64. So you get the exception.

The solution is to tell Windows that your app must start in WOW64 from the beginning. You should probably do this by building your app for x86, not Any CPU, but if that is somehow a problem (e.g. you don’t have the code), then you can use corflags to set the 32BIT flag. You just type something like this:


corflags /32BIT+ myapp.exe

For C++ applications, you can do something similar with the linker’s /clrimagetype flag.

Another choice, at least when writing in C++, is how to support the CLR. You can choose among four options: native (the default), /clr, /clr:pure, and /clr:safe. The first one is simple enough: you get a file with machine language instructions. The other three give you a file that is partially or entirely composed of MSIL. Using /clr will produce a CLR header and mostly MSIL code, but with some native code mixed in. Specifically, you get native data types but MSIL functions, unless the function uses something unsupported like function pointers. (Everyday pointers to data are supported.) You can also use #pragma unmanaged to force native code. Because these files have some native code, they must be built for a specific platform, either x86 or x64.

The /clr:pure option does what it sounds like: it gives you a file of entirely MSIL. Nonetheless, it must be built for either x86 or x64. This option is said to be equivalent to a C# project with unsafe code.

Microsoft’s documentation on the /clr and /clr:pure flags says that they can only produce x86 files, but my tests prove this to be false. If I build the C++ version of the WOW64-tester, using x64 and /clr compilation options, then it reports that it is not running in WOW64. So apparently you can in fact produce x64 applications with these options.

The last one, /clr:safe, enforces code that is verifiably type-safe—but I’m not sure what all that means. I’ve read that if you use this option, your file can run on any platform, like building as Any CPU in C#. This option requires that you use Microsoft’s C++/CLI language, formerly known as Managed C++. I know nothing about this, but people say it’s virtually a new language. I tried to build a Hello World app with printf and got innumerable compile errors, so I wasn’t able to run any tests on what this option produces.

There is also a /clr:oldSyntax option, which is like /clr:safe but with the old Managed C++ syntax rather than C++/CLI. Since Managed C++ is deprecated, I’m not sure why you’d use this for new code.

I don’t know what the /clr* options mean for P/Invoke. If I build a dll with /clr or /clr:pure, does that mean I can call its exported functions from C# without a DllImport statement? I haven’t tried. Using DllImport on these dlls doesn’t cause problems, though.

You can use a tool called dumpbin to see which /clr options were used to produce a given file. Dumpbin comes with Visual Studio and runs from the command-line:


dumpbin /CLRHEADER myapp.exe

This will print (among other things) a Flags value, which is 0 if the file was build with /clr, 1 with /clr:safe, and 3 with /clr:pure.

I’m also curious about the interaction between WOW64 and the CLR. If I run a 32-bit C# app on x64, then which comes first: WOW64 or the CLR? Is there a 64-bit CLR that can JIT-compile to either 32- or 64-bit code? Or do I have two CLRs, one for 32 bits and one for 64, and the former runs under WOW64? I suspect the answer is the latter, but I’m not sure how to tell. Either way my code is running in WOW64, so the check I described above won’t tell me anything.

I created a table to keep track of the data from all my tests. Here it is:

exe machine type binary contents managed? contains assembly? can run on x86? can run on x64? can use x86 C# dll? can use x64 C# dll? can use “Any CPU” C# dll? can use x86 C++ native dll? can use x64 C++ native dll? can use x86 C++ /clr dll? can use x64 C++ /clr dll? can use x86 C++ /clr:pure dll? can use x64 C++ /clr:pure dll?
x86 C# exe i386 MSIL yes yes yes, in CLR yes, in WOW64+CLR yes no yes yes no yes no yes no
x64 C# exe x64 MSIL yes yes no yes, in CLR no yes yes no2 yes no yes no yes
“Any CPU” C# exe i386 MSIL yes yes yes, in CLR yes, in CLR only on x861 only on x64 yes only on x861 only on x64 only on x86 only on x64 only on x86 only on x64
x86 C++ exe i386 asm no no yes, natively yes, in WOW64 ? ? ? ? ? ? ? ? ?
x64 C++ exe x64 asm no no no yes, natively ? ? ? ? ? ? ? ? ?
x86 C++ /clr exe i386 MSIL, mostly ? ? yes, in CLR yes, in WOW64+CLR ? ? ? ? ? ? ? ? ?
x64 C++ /clr exe x64 MSIL, mostly ? ? no yes, in CLR ? ? ? ? ? ? ? ? ?
x86 C++ /clr:pure exe i386 MSIL yes ? yes, in CLR yes, in WOW64+CLR ? ? ? ? ? ? ? ? ?
x64 C++ /clr:pure exe x64 MSIL yes ? no yes, in CLR ? ? ? ? ? ? ? ? ?

1There may be some option like the linker’s /CLRHEADER for C# apps.
2Can’t run on x86, and won’t be in WOW64 on x64. But see note 1.

There are still some gaps in this table. I’m not that concerned about the interactions between C++ exes and C++ dlls, so I’ve left those cells blank. I’ve also left some cell blanks regarding when C++ files are managed/unmanaged and when they contain an assembly. If I figure any of this out, I’ll update the table.

One final notable tool is ildasm (IL-disassembler), which also comes with Visual Studio. This lets you inspect the IL of an exe or dll. Most of it is over my head, but it’s intetesting to see what your code becomes.

DLL Inspector

Sunday, January 31st, 2010

Since I’ve been experimenting with 32- and 64-bit DLLs, along with the different /clr compiler options, I decided to write a quick utility to help me see how they differ. It has a small GUI:

I used this utility to build a bunch of dlls with various compiler options. I’ll post about that shortly. Here is the code for DllInfo, if anyone is interested. There is still some work to do, but what I’ve got so far served my purpose well enough:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Runtime.InteropServices;
using System.IO;

// TODO: About DllInfo...
// better display in currentFileBox

// Based on Kris Stanton's code at http://blogs.msdn.com/kstanton/archive/2004/03/31/105060.aspx

namespace DllInfo
{
    public enum MachineType
    {
        Native = 0,
        I386 = 0x014c,
        Itanium = 0x0200,
        x64 = 0x8664
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_DOS_HEADER
    {
        [FieldOffset(60)]
        public int e_lfanew;    // byte offset to the NT header
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_NT_HEADERS32
    {
        [FieldOffset(0)]
        public uint Signature;
        [FieldOffset(4)]
        public IMAGE_FILE_HEADER FileHeader;
        [FieldOffset(24)]
        public IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_NT_HEADERS64
    {
        [FieldOffset(0)]
        public uint Signature;
        [FieldOffset(4)]
        public IMAGE_FILE_HEADER FileHeader;
        [FieldOffset(24)]
        public IMAGE_OPTIONAL_HEADER64 OptionalHeader;
    }

    public struct IMAGE_FILE_HEADER {
        public ushort Machine;
        public ushort NumberOfSections;
        public ulong TimeDateStamp;
        public ulong PointerToSymbolTable;
        public ulong NumberOfSymbols;
        public ushort SizeOfOptionalHeader;
        public ushort Characteristics;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_OPTIONAL_HEADER32
    {
        [FieldOffset(0)]
        public ushort Magic;
        [FieldOffset(208)]
        public IMAGE_DATA_DIRECTORY DataDirectory;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct IMAGE_OPTIONAL_HEADER64
    {
        [FieldOffset(0)]
        public ushort Magic;
        [FieldOffset(224)]
        public IMAGE_DATA_DIRECTORY DataDirectory;
    }

    public struct IMAGE_DATA_DIRECTORY
    {
        public uint VirtualAddress;
        public uint Size;
    }

    public partial class DllInfoForm : Form
    {
        String currentDll = null;
        bool validDll = false;
        String machineType = null;
        bool isManaged = false;
        int moduleCount;
        bool hasAssembly;

        public DllInfoForm()
        {
            InitializeComponent();
            infoPanel.Paint += new PaintEventHandler(panelOnPaint);
        }

        void panelOnPaint(object obj, PaintEventArgs pea)
        {
            Graphics g = pea.Graphics;
            Brush brush = new SolidBrush(ForeColor);

            g.DrawString("valid?: ", Font, brush, 0, 0);
            g.DrawString(currentDll == null ? "" : validDll.ToString(), Font, brush, 100, 0);
            g.DrawString("machine: ", Font, brush, 0, 20);
            g.DrawString(machineType, Font, brush, 100, 20);
            g.DrawString("managed?: ", Font, brush, 0, 40);
            g.DrawString(validDll ? isManaged.ToString() : "", Font, brush, 100, 40);
            g.DrawString("has assembly?: ", Font, brush, 0, 60);
            g.DrawString(validDll ? hasAssembly.ToString() : "", Font, brush, 100, 60);
            g.DrawString("module count: ", Font, brush, 0, 80);
            g.DrawString(validDll ? moduleCount.ToString() : "", Font, brush, 100, 80);
            // TODO: is it IL or binary?
        }

        void updateDisplay() {
            if (currentDll == null)
            {
                currentFileBox.Text = "";
            }
            else
            {
                currentFileBox.Text = currentDll;
            }
            infoPanel.Invalidate();
        }

        private void chooseFile(object sender, EventArgs ea)
        {
            OpenFileDialog d = new OpenFileDialog();
            d.Filter = "dll and exe files (*.dll, *.exe)|*.dll;*.exe|All files (*.*)|*.*";
            d.Title = "Select a dll";
            if (d.ShowDialog() == DialogResult.OK)
            {
                currentDll = d.FileName;
                try
                {
                    loadDll(currentDll);
                    updateDisplay();
                }
                catch (BadImageFormatException)
                {
                    MessageBox.Show("bad image format exception");
                }
            }
        }

        public void loadDll(String dll)
        {
            byte[] data = new byte[4098];
            FileInfo fi = new FileInfo(dll);
            FileStream f;
            int n;
            ushort m;

            try
            {
                f = fi.Open(FileMode.Open, FileAccess.Read);
                // TODO: better to catch file-opening exceptions and show the user the problem.
            }
            catch
            {
                validDll = false;
                return;
            }

            n = f.Read(data, 0, 4096);
            f.Flush();
            f.Close();
            f.Dispose();

            // We must have read at least far enough to read dos_header->e_lfanew
            // Marshal.OffsetOf warns that the managed struct offsets may differ from the unmanaged,
            // but this is only true if the data types are not blittable.
            // Since C# lets me obtain points to these structs, I know that they are blittable,
            // so I can disregard the warning about Marshal.OffsetOf.
            if (n < (int)Marshal.OffsetOf(typeof(IMAGE_DOS_HEADER), "e_lfanew") + sizeof(int))
            {
                validDll = false;
                return;
            }

            unsafe
            {
                fixed (byte* d = data)
                {
                    IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)d;

                    // Make sure we read enough bytes to follow e_lfanew and read everything else:
                    // Use the 64-bit values since they are a few bytes larger.
                    // If we're running on 32 bits, there will still be other bits in the dll after the header,
                    // so we won't reject any false positives.
                    if (n e_lfanew
                        + (int)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS64), "OptionalHeader") // +24
                        + (int)Marshal.OffsetOf(typeof(IMAGE_OPTIONAL_HEADER64), "DataDirectory") // +224
                        + (int)Marshal.OffsetOf(typeof(IMAGE_DATA_DIRECTORY), "Size")  // +4
                        + sizeof(uint)) // +4
                    {
                        validDll = false;
                        return;
                    }

                    IMAGE_NT_HEADERS32* nt32_header = (IMAGE_NT_HEADERS32*)(d + dos_header->e_lfanew);

                    m = nt32_header->FileHeader.Machine;

                    validDll = Enum.IsDefined(typeof(MachineType), (Int32)m);
                    if (validDll)
                    {
                        machineType = ((MachineType)m).ToString();

                        // 0x10b indicates a PE32 assembly
                        // 0x20b indicates a PE32+ assembly (i.e. 64-bit, hence either x64 or Itanium)
                        if (nt32_header->OptionalHeader.Magic == 0x20b)
                        {
                            isManaged = ((IMAGE_NT_HEADERS64*)nt32_header)->OptionalHeader.DataDirectory.Size > 0;
                        }
                        else
                        {
                            isManaged = nt32_header->OptionalHeader.DataDirectory.Size > 0;
                        }
                    }
                }
            }

            if (validDll)
            {
                Assembly a;
                Module mod;
                PortableExecutableKinds peKind;
                ImageFileMachine machine;

                try
                {
                    a = Assembly.LoadFile(dll);
                    hasAssembly = true;
                    moduleCount = a.GetModules().Length;
                    // TODO: sanity check that PEKind matches what we inferred from the binary?
                    /*
                    m = a.GetModules()[0]; // TODO: multi-module assemblies?
                    m.GetPEKind(out peKind, out machine);
                    dllType = peKind.ToString();
                    machineType = machine.ToString();
                      */
                }
                catch (BadImageFormatException)
                {
                    // This is not quite right:
                    // The file may have an assembly but be opened on the wrong platform (32 vs 64 bits).
                    hasAssembly = false;
                    moduleCount = 0;
                }
                catch (FileLoadException)
                {
                    hasAssembly = true;
                    moduleCount = -1;
                }

            }
        }
    }
}

Enabling 64-bit Support in Visual Studio 2008

Saturday, January 23rd, 2010

With all my confusion about 32- vs. 64-bits in C# and C++, I wanted to build some C++ exes and dlls in 64 bits to work out how everything fit together. But it took me a while to figure out how to do this in Visual Studio. For a C# project, there is an easy-to-find option under Build called Platform Target, with choices called Any CPU, x86, and x64. But there is nothing quite so evident among the properties for a C++ project.

To build a 64-bit version for your C++ app, you should open the Properties dialog and then click the Configuration Manager button in the upper-right corner. Then select the Active Solution Platform dropdown menu, and choose <New...>. Select x64, and request to copy over the old Win32 properties. Now you can build your project for either 32 or 64 bits. Visual Studio maintains separate properties for each. You use the Configuration Manager to set the “Active” platform, which is what actually gets built, but you can adjust the properties of either platform using the Platform dropdown at the top of the properties dialog.

Once you’ve enabled both platforms for your project, make sure x64 is set as the active target, and take at look at the x64 properties under Linker:Advanced. You should see one called Target Machine, set to MachineX64 (/MACHINE:X64). Under the Win32 version, this read MachineX86 (/MACHINE:X86), but Visual Studio should have flipped it automatically when you created the x64 target. If not, set it correctly now.

Note that if you have a mismatch between the Platform and the linker’s setting, you’ll get a build error like this:

fatal error LNK1112: module machine type ‘X86′ conflicts with target machine type ‘x64′

So you need MachineX86 with a Win32 platform, and MachineX64 with the x64 platform.

Now you should be able to build both 32- and 64-bit versions of your app!

Referencing a non-CLR DLL

Monday, January 18th, 2010

In my last post, I mentioned that I configured the C++ DLL to compile with the /clr option. I found this to be necessary in order to use the Visual Studio Add Reference command, so that the C# app could find the DLL at runtime. For some reason, Add Reference failed unless I used /clr. But strangely, I found that if I compiled without /clr and copied the DLL into my bin/Debug folder, everything still worked. And that isn’t too surprising: P/Invoke lets you call plain old Win32 DLLs.

But why wasn’t Add Reference working? Well, it turns out that Add Reference only lets you reference assemblies, and a win32 dll is not an assembly; you need CLR support for that. I had assumed Add Reference was some kind of generic build dependency, but I guess it’s something more specific. This is kind of disappointing. Who ever heard of an IDE without some way of managing project dependencies?

At first I thought my only option was to use Pre- and Post-Build commands. If you go to the Build Events tab of the C# properties window, you can see spaces for defining DOS commands that run before and after your build. VS supplies a bunch of macros you can use for important paths of other bits of information. So one way of solving my problem is to copy the DLL by hand. In the pre-build box, I entered this command:


copy "$(SolutionDir)$(Configuration)/MathDll.dll" "$(TargetDir)"

But that seems sort of like a hack. It leaves Visual Studio completely innocent of the project dependency. Later I found a slightly better (but still not so great) way of doing it. I got rid of this pre-build step, and under the C# project I used the Add Existing Item command. Then I navigated to the dll and added it to the C# project. I set its Copy to Output Directory property to Copy if newer. I left the Build Action property as Content, which seems to mean that Visual Studio just leaves it untouched. So now, as long as I’ve set up the dll portion to run first, the dll gets copied properly. This seems a little better than the DOS way, because at least Visual Studio is somewhat aware of that the C# project uses the dll, and that fact is also less hidden from developers (i.e. me, six months later).

UPDATE: On second thought, my first approach seems better. Because of the $(Configuration) macro, it works whether I’m building a Debug or Release version. But the Add Existing Item approach forces me to point to a dll in either the Debug or Release directory.

Perhaps the best solution is simply to compile with /clr. But I wanted to get both ways working, because I want to try both versions to see if either will resolve another error I’m getting, to be explained later. . . .

UPDATE 2: One problem I’ve found with the Pre-Build shell code is that even with $(Configuration), one line doesn’t work for all configurations. This is because if you set up, say, an “x64″ configuration in addition to the default “Any CPU” one, then the folder structure isn’t parallel. The default configuration has a bin/Debug folder, whereas the x64 configuration has a bin/x64/Debug folder. This difference is not captured in the $(Configuration) macro. You can work around this because Visual Studio maintains separate property values for each configuration, so you can set up different pre-build shell commands for different configurations. But this is sort of annoying.

Calling a C++ DLL from C#

Monday, January 18th, 2010

If I’m going to borrow some C++ code for a folder-picker dialog box, then first I have to figure out how to write a C++ DLL that is useable from C#. Microsoft has a nice tutorial about creating and using DLLs, but it’s in pure C++. “No problem,” I thought. “I know how to use P/Invoke.” Well, it turns out that it’s not so easy.

To keep things simple, I figured I’d write an app to do math, as in that MS tutorial. So I used Visual Studio to create a C# console application, and I wrote this code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace MixedDll
{
    class Program
    {
        [DllImport("MathDll.dll")]
        static extern int Add(int a, int b);

        static void Main(string[] args)
        {
            Console.WriteLine(Add(21, 21));
            Console.ReadLine();
        }
    }
}

As you can see, I’m planning to write a dll called MathDll.dll, which will export one function: int Add(int a, int b). This requires adding a second project to our solution. In Visual Studio, each “solution” can have multiple “projects,” where each project builds some artifact like a dll or exe. As far as I can tell, you may only use one language within a given project.

Following the MS tutorial, I chose to create an empty C++ project rather than following any of the templates. Then in the settings (under Configuration Properties:General), I changed Configuration Type from .exe to .dll. I also added support for the Common Language Runtime (/clr). Then I added two files. First was MathDll.h:


extern "C" {
    __declspec(dllexport) int Add(int a, int b);
}

The second file was MathDll.cpp:


#include "MathDll.h"

extern int Add(int a, int b) {
    return a + b;
}

Finally, I added a reference from the C# project to the C++ project. In the Solution Explorer on the right, I right-clicked on References under MixedDll. Then I went to the Projects tab and selected MathDll. Oops! Visual Studio wouldn’t let me add the reference! Everything built, but I couldn’t get the IDE to supply access to the dll at runtime. Well, I figured I could do that myself. So after building everything, I manually copied MathDll.dll to MixedDll/bin/Debug. That’s where MixedDll.exe gets built, so I figured it should be able to pick up the dll.

Unfortunately, my little hack didn’t work. When I ran the program, I got a BadImageFormatException. It turns out this is what happens when you mix 32-bit and 64-bit binaries. As far as I can tell, a 32-bit exe can only use 32-bit dlls, and a 64-bit exe can only use 64-bit dlls. My C++ project was building as 32-bit, but my C# app was building as “Any CPU” (under Properties:Build:Platform Target), which I guess results in a 64-bit product.

The right solution would have been to build a 64-bit dll, but for some reason Visual Studio wasn’t giving me that option. So I switched the C# app to 32-bit and tried again. This time I was able to add the reference (no more kludgy manual copy)! When I rebuilt everything and ran the program, I saw my output: 42!