More on extending the marshal_as library

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.

Advertisements

One thought on “More on extending the marshal_as library

  1. Nice article man, please more C++ / CLI !

    the new Marshal_as lib has me very excited for the release of visual studio orcas.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s