Feeds:
Posts
Comments

Archive for the ‘VC++ Orcas’ Category

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 »

In my previous blog entry, I talked about extending marshal_as to support other type conversions in addition to the default ones. But the examples I used didn’t need to handle resource deallocation. When you have type conversions which require explicit resource deallocation, you have to handle it slightly differently. As an example I have written some code that’ll extend marshal_as to support conversions between .NET Font objects and native Windows HFONT structures

namespace msclr
{
    namespace interop
    {
        template<> ref class context_node<System::Drawing::Font^, HFONT>
        : public context_node_base
        {
        private:
            System::Drawing::Font^ _font;

        public:
            context_node(System::Drawing::Font^% to, HFONT from)
            {
                to = _font = System::Drawing::Font::FromHfont((IntPtr)from);
            }

            ~context_node()
            {
                this->!context_node();
            }

        protected:
            !context_node()
            {
                delete _font;
            }
        };

        template<> ref class context_node<HFONT, System::Drawing::Font^>
        : public context_node_base
        {
        private:
            HFONT _hFont;

        public:
            context_node(HFONT& to, System::Drawing::Font^ from)
            {
                to = _hFont = (HFONT)from->ToHfont().ToPointer();
            }

            ~context_node()
            {
                this->!context_node();
            }

        protected:
            !context_node()
            {
                DeleteObject(_hFont);
            }
        };
    }
}

I’ve added two specializations of the context_node template class which is used by the marshal_context class to handle conversions that need a context. In the constructors I create the object that’s requested and in the destructor/finalizer I free the resource. In the case of HFONT, I have called DeleteObject whereas for Font, I have called delete (which calls Dispose). I need not have done that for Font as the Font finalizer would have come into play eventually, but for GDI objects it’s preferable to free them as soon as they are not required as they tend to be rather heavy on the memory side.

Using these conversions is pretty similar to how marshal_as conversions are used for const char* or BSTR (where we use a context object too).

HFONT hFont = CreateSampleFont();

//...

marshal_context context;

System::Drawing::Font^ font =
    context.marshal_as<System::Drawing::Font^>(hFont);
HFONT hFontCopy = context.marshal_as<HFONT>(font);

//...

DeleteObject(hFont);

That’s it. Pretty straightforward to extend and to use.

Read Full Post »

A couple of blog entries ago, I had written about the marshal_as library that is introduced in Orcas and how it’s very useful for mixed-mode string conversions. While the built-in functionality only allows string conversions, it’s also possible to extend marshal_as functionality to support other type conversions. As an example of doing this, I have written a sample extension that supports converting between the Windows Forms Rectangle structure and the Win32 RECT structure. For the sake of completion I have also added specializations for the MFC CRect wrapper (which is a thin wrapper around the RECT structure). Here’s my extension (put into a separate header file) :-

namespace msclr
{
    namespace interop
    {
        template<> System::Drawing::Rectangle
            marshal_as<System::Drawing::Rectangle, RECT> (
            const RECT& from)
        {
            return System::Drawing::Rectangle(from.left, from.top,
                from.right - from.left, from.bottom - from.top);
        }

        template<> System::Drawing::Rectangle marshal_as<
            System::Drawing::Rectangle, CRect> (
            const CRect& from)
        {
            return System::Drawing::Rectangle(from.left, from.top,
                from.Width(), from.Height());
        }

        template<> RECT marshal_as<RECT, System::Drawing::Rectangle>(
            const System::Drawing::Rectangle& from)
        {
            System::Drawing::Rectangle rectangle = from; //remove const
            RECT rect = {rectangle.Left, rectangle.Top,
                rectangle.Right, rectangle.Bottom};
            return rect;
        }

        template<> CRect marshal_as<CRect, System::Drawing::Rectangle>(
            const System::Drawing::Rectangle& from)
        {
            System::Drawing::Rectangle rectangle = from; //remove const
            return CRect (rectangle.Left, rectangle.Top,
                rectangle.Right, rectangle.Bottom);
        }
    }
}

Effectively I’ve added four specializations for the four conversions that I need. Note how I have put the conversions into the msclr::interop namespace. This is to allow me (and anyone else) to use these additional conversions the same way I’d be using marshal_as for the regular conversions.

Now using these conversions would be quite trivial as show below.

//To Rectangle

RECT rect = {10, 10, 110, 110};
System::Drawing::Rectangle rectangle =
    marshal_as<System::Drawing::Rectangle>(rect);

CRect mfcRect(20, 20, 220, 220);
rectangle = marshal_as<System::Drawing::Rectangle>(mfcRect);

//From Rectangle

RECT rectBack = marshal_as<RECT>(rectangle);

CRect mfcRectBack = marshal_as<CRect>(rectangle);

One important thing to be aware of is that in all four conversions I’ve added there is no need to handle context as there is no explicit need for memory deallocation. This may not always be the case as we’ll see in the next blog entry (hopefully soon).

Read Full Post »

The need to marshal between native and managed types is a very frequent scenario in mixed-mode programming. This is specially true when it comes to strings – when you’ve got MFC strings, COM strings, standard C++ strings and CLR strings and need to convert between those types. In fact that’s what prompted me to write the StringConvertor class for managed-unmanaged string conversions. While I did realize that I had misspelled converter as convertor I decided to leave it like that so I got a unique class-name and that way I could avoid Google dilution (there are dozens of other StringConverter classes, specially Java based ones).

Anyway, in the Orcas release of Visual C++, the VC++ team have added a mixed-mode marshalling library which primarily consists of the marshal_as template function. While marshal_as is technically not limited to string conversions, that is its most important role as of now. Using it is very similar to using one of the C++ cast operators such as static_cast – though be aware that you are not really casting here, you are doing a conversion – which may or may not be a different thing from a mere cast.

Here’s a code snippet that shows how to convert various native strings to System::String

String^ clrString;

const char* pcszHello = "hello world";
clrString = marshal_as<String^>(pcszHello);

wchar_t* pwszHello = L"hello wide world";
clrString = marshal_as<String^>(pwszHello);

bstr_t bstrtHello("hello bstr_t world");
clrString = marshal_as<String^>(bstrtHello);

std::string stdHello = "hello from std::string";
clrString = marshal_as<String^>(stdHello);

CString mfcString("hello from CString");
clrString = marshal_as<String^>(mfcString);

CComBSTR atrBSTR(L"hello from CComBSTR");
clrString = marshal_as<String^>(atrBSTR);

The reverse conversion is also similar.

String^ clrString = "Original System::String";

std::string stdHello = marshal_as<std::string>(clrString);
CString mfcString = marshal_as<CString>(clrString);
CComBSTR atrBSTR = marshal_as<CComBSTR>(clrString);

You cannot directly use marshal_as for converting a String^ to a const char*, a const wchar_t* or a BSTR – because those conversions require the unmanaged resources to be freed after use. For those, you need to use a context object as shown below.

marshal_context context;

const char* pcszHello = context.marshal_as<const char*>(clrString);
const wchar_t* pcwszHello = context.marshal_as<const wchar_t*>(clrString);
BSTR bstrString = context.marshal_as<BSTR>(clrString);

Console::WriteLine(context._clean_up_list.Count);

The context object keeps track of the allocated objects and frees them in its destructor. Internally it maintains a linked list of objects that are allocated, and the output of the Console::WriteLine in the above code will be 3 (as we have allocated three objects using the context object). Initially I found this a little annoying to do, but I couldn’t think of any alternate solution that was more elegant and where we could avoid using the context object. In fact, in my StringConvertor class I had internally used an std::vector to store all allocated objects so I could free them in the destructor.

Read Full Post »

Follow

Get every new post delivered to your Inbox.