Feeds:
Posts
Comments

Archive for June, 2010

A month or two back, I had to write a launcher app that would allow/disallow the running of select installers based on various conditions and config files. Since this would run prior to any of the MSIs, and thus couldn’t assume the presence of any dependencies like .NET or the VC++ runtime, I wrote it as a statically linked MFC dialog app using VC++ 2008. All was well with initial testing. But during a final testing phase, the launcher failed to run on a fresh Windows 2000 box with an error about a missing gdiplus.dll.

Windows XP and later OSes like Vista and Windows 7 have GDI+ by default though you may need to apply patches for the latest updates on XP. Windows 2000 predates GDI+ and thus does not have GDI+ by default though a redistributable is available as a separate download. So that’s why it failed. But why is there a dependency at all? I had always assumed that a statically linked MFC app would run anywhere. The it struck me – the BCG stuff that they added to MFC starting VC++ 2008! That code used GDI+ and thus had a GDI+ dependency.

Obviously I couldn’t include the GDI+ redistributable for the launcher app and I didn’t want to remotely take the risk of manually copying along the GDI+ DLL (or any extra files it needs) what with the various updates out there. Eventually, I rewrote the app as a plain Win32 API dialog app (the app was kinda simple, so it didn’t take me too long). I know not many people support Windows 2000 today, but some of our clients are still on that OS, and so it was important for us to support it. Anyway, this is just something to keep in mind when using MFC to write a stub executable that should run anywhere.

Read Full Post »

This is based on a recent thread on the MSDN forums. Someone had code that looked like this:

public class CustomObject<T>
{
    Object _obj;

    public Object Value
    {
        get
        {
            return _obj;
        }
    }

    public static explicit operator CustomObject<T>(T obj)
    {
        return new CustomObject<T>() { _obj = obj };
    }
}

class App
{
    static void Main()
    {
        var tmp1 = (CustomObject<Object>)true; // from bool

        var tmp2 = (CustomObject<Object>)12; // from int

        // The following code throws a System.InvalidCastException
        // Unable to cast object of type 'System.Object' to
        // type 'CustomObject`1[System.Object]'
        var tmp3 = (CustomObject<Object>)new Object(); // from object
    }
}

The code compiles fine but the third conversion results in an InvalidCastException. And he was quite puzzled by it.

The answer is simple if you think about it, and the exception that’s thrown is a dead giveaway. When you have an object there, the compiler sees that as a downcast (casting from base to a more derived type). The reason is that CusObject<T> is derived from Object (implicitly) and so when the type being converted is Object, it will not call the explicit (or implicit) conversion operator, instead it will generate a castclass IL instruction which will obviously fail.

To make that more clear, forget the “generics” and take this example:

class Base
{
}

class Derived : Base
{
    public static explicit operator Derived(Base b)
    {
        return new Derived();
    }
}

That will not compile and you’ll see this:

Error 1 ‘Derived.explicit operator Derived(Base)': user-defined conversions to or from a base class are not allowed

Of course when you use a generic parameter, the compiler cannot anticipate that you’d try doing this, and so it will let you declare the operator. And when you later have an ambiguous situation where you cast from base to derived, it will simply ignore the explicit operator and instead do a downcast.

In the MSDN thread, Louis.fr pointed out the appropriate section in the language spec that talks about this. For those interested it’s 10.10.3. Quoting below:

However, it is possible to declare operators on generic types that, for particular type arguments, specify conversions that already exist as pre-defined conversions.

In cases where a pre-defined conversion exists between two types, any user-defined conversions between those types are ignored.

Read Full Post »

There was a recent thread in the MSDN forums where someone was concerned about the behavior of Type.GetElementType. His example was similar to the following:

char [][,][] arr = new char[2][,][];
Console.WriteLine(arr.GetType().GetElementType());

The output he got was:

System.Char[][,]

This puzzled him no end because the element type is clearly char[,][]. He was wondering if this was a bug in GetElementType or even if it was a bug in the C# compiler (incorrectly parsing the array declaration).

Well there is no mystery here. Array types (or rather the runtime type for an array) have a ToString implementation that displays the array using a display format closely resembling the IL syntax for arrays, and not the C# syntax. This is very easily verified with the following code:

Console.WriteLine(typeof(char[][,][,,]));

The output here is:

System.Char[,,][,][]

This is a good idea since the C# array syntax is not universal among CLI languages anyway. Both VB.NET and C++/CLI use array syntax that’s different from this.

Read Full Post »

Pon Sayasith emailed me a couple of weeks ago saying he’d bought my C++/CLI book and then went on to ask me what I thought of a mixed mode static library that has a managed class and a native wrapper, that is then consumed by a native C++ app. My first reaction (which turned out to be wrong) was that this would not be possible. But I was basically over-thinking there.

My initial thought was that when you have a C++ project with say 1 cpp file compiled as /clr, you are still forced to change project settings to match those that support the /clr switch. But when you link with a lib with a /clr compiled cpp file, your native project settings are not changed. I wasn’t sure if that was alright to do and whether the compiler was unaware of the fact that the lib needs managed support.

But I did a quick test and apparently, once the compiler sees that a linker lib is mixed-mode, then it knows how to handle that and the main exe is itself generated as a .NET executable (with mscoree.dll called and all that). This actually has an advantage in that you don’t need to tweak project settings to support /clr compilation.

So if you want to avoid tweaking your main project’s settings just to enable /clr compilation on a couple of cpp files, then this approach is an excellent workaround for you. The static lib project will need to have its project settings tweaked for /clr compilation (even for selective cpp files), but your main project settings remain unchanged, and just as you want it.

Read Full Post »

In an earlier FAQ entry, I talked about how you can show a previously closed Windows Forms form. Well the same holds true for a WPF window and for the same underlying reason. When you close a WPF window, the native window is closed and destroyed. So trying to re-show it will just throw an exception. The solution is to either hide/show windows as required, or to instantiate and show a new window whenever that’s needed.

Read Full Post »

This question or a similar variation pops up in the forums once in a while. The core problem is that while null terminated char arrays can be marshaled to a System.String fairly easily, with other unmanaged arrays the marshaller cannot know for sure what size of array to create. The solution is to marshal the argument as an IntPtr and then in the calling code, the user can manually create a managed array and copy the data into it. This assumes that the unmanaged API has a size parameter (which it invariably does) that indicates the length of the unmanaged array. Here’s some example code that shows how this is done:

C++ code

typedef long (CALLBACK * READDATA)(unsigned char * data, int length);

extern "C" __declspec(dllexport)  void __stdcall SomeFunc(READDATA rd)
{
 unsigned char data[5] = {'a', 'b', 'c', 'd', 'e'};
 rd(data, 5);
}

And here’s the calling code:

C# code

delegate int ReadDataDelegate(IntPtr data, int len);

[DllImport("SimpleLib.dll")]
static extern void SomeFunc(ReadDataDelegate d);

private static void CallNativeWithCallback()
{
    ReadDataDelegate newCB = new ReadDataDelegate((data, len) =>
    {
        byte[] array = new byte[len];
        Marshal.Copy(data, array, 0, len);
        foreach (byte b in array)
        {
            Console.WriteLine((char)b);
        }
        Console.WriteLine();
        return 0;
    });
    SomeFunc(newCB);
}

Read Full Post »

This one comes up in the forums at least once a week. The scenario is where someone shows a form, closes it while retaining the handle, and then tries to show it again by calling Show or ShowDialog on the closed form. This throws an exception that says the object has been disposed.

Here’s my standard answer. You cannot re-show a form once it’s closed because the underlying window is destroyed. You can hide the form and then re-show it as required thereby reusing the same form instance.

Alternatively, for modal dialogs, instantiate a local form variable and call ShowDialog on that. So each time it’s a new form. And this way you don’t need to keep the form in memory all the time, specially if it’s an options dialog that’s rarely brought up.

Read Full Post »

Follow

Get every new post delivered to your Inbox.