{"id":174,"date":"2022-07-15T22:34:14","date_gmt":"2022-07-15T22:34:14","guid":{"rendered":"https:\/\/edais.co.uk\/blog\/?p=174"},"modified":"2022-08-30T20:45:03","modified_gmt":"2022-08-30T20:45:03","slug":"python-managed-win32-gdi-resources","status":"publish","type":"post","link":"https:\/\/edais.co.uk\/blog\/2022\/07\/15\/python-managed-win32-gdi-resources\/","title":{"rendered":"Python managed Win32 GDI resources"},"content":{"rendered":"\n<p><em>A quick note before we begin, whilst this article specifically describes a way of writing cleaner and safer Win32 GDI code in Python, these same techniques could be applied to any corresponding API which requires manual resource management.<\/em><\/p>\n\n\n\n<p>A task came up recently which required utilising some old Win32 GDI APIs for a legacy application maintenance.&nbsp; There are various examples online of using the <a href=\"https:\/\/docs.python.org\/3\/library\/ctypes.html#module-ctypes\">ctypes<\/a> library in Python for getting access to the Win32 APIs, however the code tends to be largely a straight port of C-style code without utilising any pythonic niceties.<\/p>\n\n\n\n<p>A typical construct seen throughout GDI code is the <strong>create<\/strong>, <strong>use<\/strong>, <strong>destroy <\/strong>cycle, e.g:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>from ctypes import windll\nhDC = windll.gdi32.CreateCompatibleDC(0) # Create\n# Use Device Context here\nwindll.gdi32.DeleteDC # Destroy<\/code><\/pre><\/div>\n\n\n\n<p>One issue with this is that different GDI constructs use different clean-up calls.&nbsp; For example, the handle returned by <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/winuser\/nf-winuser-getdc\">GetDC<\/a> must be disposed with <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/winuser\/nf-winuser-releasedc\">ReleaseDC<\/a>, whereas the handle created by <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/wingdi\/nf-wingdi-createbitmap\">CreateBitmap<\/a> should be disposed with <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/wingdi\/nf-wingdi-deleteobject\">DeleteObject<\/a>.&nbsp; Making sure the correct clean-up method is called for each resource type, especially as the complexity of the code increases can become an issue.<\/p>\n\n\n\n<p>Since the functions are opaque calls into DLLs, there is no code hinting available when writing the code, which requires either an encyclopaedic knowledge of the Win32 API, or the GDI documentation permanently open on a second screen.<\/p>\n\n\n\n<p>Additionally, there are calls like <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/wingdi\/nf-wingdi-selectobject\">SelectObject<\/a>, which is used to bind a GDI resource with a Device Context, that can create subtle potential for GDI leaks if not handled correctly.<\/p>\n\n\n\n<p>For instance, you\u2019ll often find code examples like this online:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>hPen = windll.gdi32.CreatePen(PS_SOLID, 3, 0xFF0000)\nwindll.gdi32.SelectObject(hDC, hPen)\n# Use pen here\nwindll.gdi32.DeleteObject(hPen) # Leak! Still selected into the DC, pen isn\u2019t deleted!<\/code><\/pre><\/div>\n\n\n\n<p>The correct way to handle DC object selection is to retain the handle returned by the initial <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/wingdi\/nf-wingdi-selectobject\">SelectObject<\/a> call (which will typically be a GDI stock object on a fresh DC), then once the GDI object is no longer required, re-select that handle back into the DC before deleting it.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>hPen = windll.gdi32.CreatePen(PS_SOLID, 3, 0xFF0000)\nhOldPen = windll.gdi32.SelectObject(hDC, hPen)\n# Use pen here\nwindll.gdi32.SelectObject(hDC, hOldPen) # De-select\nwindll.gdi32.DeleteObject(hPen) # Then delete<\/code><\/pre><\/div>\n\n\n\n<p>All this clean-up code can get quite verbose, which makes it more difficult to reason about what the code is doing in amongst all the resource management and obscure GDI hoops that must be jumped through.<\/p>\n\n\n\n<p>Finally, error handling can become tricky with this sort of code and a source of GDI leaks, since unless the GDI calls are unwound in the correct order then there is potential for those resources to be left hanging around if an exception occurs.<\/p>\n\n\n\n<p>So whilst waiting for inspiration to strike and getting on with writing another part of the application that dealt with reading files, I was writing some standard file access code e.g.:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>with open(&quot;file.xyz&quot;, &quot;r&quot;) as f:\n\tfileData = f.read()<\/code><\/pre><\/div>\n\n\n\n<p>It occurred to me that although I\u2019d used the <a href=\"https:\/\/docs.python.org\/3\/reference\/compound_stmts.html#with\">with<\/a> statement to ensure that the file is properly closed in case of error, that I\u2019d never really investigate <em>how<\/em> it worked.&nbsp; It turns out that this uses something called a <a href=\"https:\/\/docs.python.org\/3\/reference\/datamodel.html#context-managers\">statement context manager<\/a>, which handles entry into and exit from a runtime context.<\/p>\n\n\n\n<p>A quick check in the documentation reveals that implementing our own context manager is straightforward, a rudimentary example of this would be:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>class MyScope(object):\n\tdef __enter__(self):\n\t\tprint(&quot;Entering scope!&quot;)\n\t\n\tdef __exit__(self, type, value, tb):\n\t\tprint(&quot;Exiting scope!&quot;)\n\nwith MyScope():\n\tprint(&quot;In scope&quot;)<\/code><\/pre><\/div>\n\n\n\n<p>This prints:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Entering scope!\nIn scope\nExiting scope!\n<\/pre>\n\n\n\n<p>Nice, so now we can execute code when entering and existing from a scope block.&nbsp; What\u2019s really nice though, is that the exit code will still be called even in the case an error is raised, similar to a try \/ finally block:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>with MyScope():\n\traise Exception(&quot;nope&quot;)<\/code><\/pre><\/div>\n\n\n\n<p>This outputs:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Entering scope!\nExiting scope!\nException: nope<\/pre>\n\n\n\n<p>As we can see, the exit block gets called <em>before<\/em> the exception is bubbled up to the caller.<\/p>\n\n\n\n<p>So, with that little aside into context mangers out of the way, is there a way that these two concepts can be tied back together, and the narrative of this article brought back on track?&nbsp; Thankfully, yes.<\/p>\n\n\n\n<p>So back in GDI world, the familiar <strong>create<\/strong>, <strong>use<\/strong>, <strong>destroy <\/strong>cycle seems to map well to the <strong>enter<\/strong>, <strong>use<\/strong>, <strong>exit <\/strong>functionality of the context manager, so let\u2019s try merging them together.&nbsp; A new utility class can be built for each pair of calls, that can take the input parameters in the constructor, calls the object creation method in enter, and the corresponding destruction method in exit:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>class CreateCompatibleDC(object):\n\t&quot;&quot;&quot;Context manager for GDI32 CreateCompatibleDC function&quot;&quot;&quot;\n\tdef __init__(self, hRefDC=0):\n\t\tself.hRefDC = hRefDC\n\t\n\tdef __enter__(self):\n\t\tprint(&quot;Create compatible DC&quot;)\n\t\tself.hDC = windll.gdi32.CreateCompatibleDC(self.hRefDC)\n\t\treturn self.hDC\n\t\n\tdef __exit__(self, type, value, tb):\n\t\tprint(&quot;Delete DC&quot;)\n\t\twindll.gdi32.DeleteDC(self.hDC)<\/code><\/pre><\/div>\n\n\n\n<p>The class can now be utilised in the calling code like this:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>with CreateCompatibleDC(0) as hDC:\n\tprint(&quot;Use DC: %d&quot; % hDC)<\/code><\/pre><\/div>\n\n\n\n<p>which outputs:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create compatible DC\nUse DC: -1157555815\nDelete DC\n<\/pre>\n\n\n\n<p>Great, it looks like the calls are all being made in the right places, the code is much simpler without all the boilerplate GDI stuff getting in the way.&nbsp; The Python class also offers code completion in the IDE on the parameter(s) required and it even properly cleans up on exceptions!<\/p>\n\n\n\n<p>Of course, in any production code the print messages wouldn\u2019t be used, they\u2019re just there to show that the code is doing the right things at the right times.<\/p>\n\n\n\n<p>This same technique can the be used for other calls too, for example:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>class CreatePen(object):\n\t&quot;&quot;&quot;Context manager for GDI32 CreatePen function&quot;&quot;&quot;\n\tdef __init__(self, style, width, colour):\n\t\tself.style = style\n\t\tself.width = width\n\t\tself.colour = colour\n\t\n\tdef __enter__(self):\n\t\tprint(&quot;Create pen&quot;)\n\t\tself.hPen = windll.gdi32.CreatePen(self.style, self.width, self.colour)\n\t\treturn self.hPen\n\t\n\tdef __exit__(self, type, value, tb):\n\t\tprint(&quot;Delete pen&quot;)\n\t\twindll.gdi32.DeleteObject(self.hPen)\n\nclass SelectObject(object):\n\t&quot;&quot;&quot;Context manager for GDI32 SelectObject function&quot;&quot;&quot;\n\tdef __init__(self, hDC, hObj):\n\t\tself.hDC = hDC\n\t\tself.hObj = hObj\n\t\n\tdef __enter__(self):\n\t\tprint(&quot;Select object&quot;)\n\t\tself.hOldObj = windll.gdi32.SelectObject(self.hDC, self.hObj)\n\t\treturn self.hOldObj\n\t\n\tdef __exit__(self, type, value, tb):\n\t\tprint(&quot;Deselect object&quot;)\n\t\twindll.gdi32.SelectObject(self.hDC, self.hOldObj)<\/code><\/pre><\/div>\n\n\n\n<p>Now the code from the beginning of the article can be written more simply as:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>with CreateCompatibleDC() as hDC:\n\twith CreatePen(PS_SOLID, 3, 0xFF0000) as hPen:\n\t\twith SelectObject(hDC, hPen):\n\t\t\tprint(&quot;Use Pen: %d in DC: %d&quot; % (hPen, hDC))<\/code><\/pre><\/div>\n\n\n\n<p>Note here that we\u2019re now utilising the default value specified in the create compatible DC class constructor, and that the returned handle from the select object call is ignored since it\u2019s only useful internally for clean-up.<\/p>\n\n\n\n<p>This outputs:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create compatible DC\nCreate pen\nSelect object\nUse Pen: -399500450 in DC: 553719962\nDeselect object\nDelete pen\nDelete DC\n<\/pre>\n\n\n\n<p>Since this is starting to resemble a pyramid of doom, all those with statements can get collapsed into one using backslash line continuation characters, and are still executed in order even in the case of error:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-python\" data-lang=\"Python\"><code>with CreateCompatibleDC() as hDC, \\\n\tCreatePen(PS_SOLID, 3, 0xFF0000) as hPen, \\\n\tSelectObject(hDC, hPen):\n\traise Exception(&quot;testing&quot;)<\/code><\/pre><\/div>\n\n\n\n<p>This prints:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create compatible DC\nCreate pen\nSelect object\nDeselect object\nDelete pen\nDelete DC\nException: testing\n<\/pre>\n\n\n\n<p>So as we can see, the clean-up code gets executed in order, so even if errors occur there is a guarantee that no GDI objects will get leaked.<\/p>\n\n\n\n<p>Hopefully this technique can be utilised in your own code to help manage resources, clean up code and prevent unmanaged resource leaks.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A quick note before we begin, whilst this article specifically describes a way of writing cleaner and safer Win32 GDI code in Python, these same techniques could be applied to any corresponding API which requires manual resource management. A task came up recently which required utilising some old Win32 GDI APIs for a legacy application &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/edais.co.uk\/blog\/2022\/07\/15\/python-managed-win32-gdi-resources\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Python managed Win32 GDI resources&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[32],"tags":[36,34,33,35],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/posts\/174"}],"collection":[{"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=174"}],"version-history":[{"count":7,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/posts\/174\/revisions"}],"predecessor-version":[{"id":182,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/posts\/174\/revisions\/182"}],"wp:attachment":[{"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/edais.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}