Jekyll2019-01-09T22:13:22+00:00https://retep998.github.io/blog/feed.xmlWindowsBunnyThe bunny that nibbles on Windowswinapi 0.32017-12-01T00:00:00+00:002017-12-01T00:00:00+00:00https://retep998.github.io/blog/winapi-0.3<p>For over a year people have been wondering when the next version of winapi would be published, and today I am happy to announce that <code class="highlighter-rouge">winapi</code> 0.3 has finally been published to crates.io! This new version has a lot of changes, so this post will go over them and cover any changes that will need to be made to your own code when migrating to this new version.</p>
<h2 id="the--sys-crates-are-dead-long-live-the-winapi-behemoth">The <code class="highlighter-rouge">-sys</code> crates are dead. Long live the <code class="highlighter-rouge">winapi</code> behemoth.</h2>
<p>In previous versions of <code class="highlighter-rouge">winapi</code>, function bindings were separated into their own independent crates based on which import library contained those symbols. For example, the <code class="highlighter-rouge">MessageBoxW</code> function is exported from <code class="highlighter-rouge">user32.lib</code>, and was thus bound in the <code class="highlighter-rouge">user32-sys</code> crate.</p>
<p>In 0.3, this is no longer true: the <code class="highlighter-rouge">winapi</code> crate contains all types, constants, macros, <em>and</em> functions. As such, dependencies on all <code class="highlighter-rouge">-sys</code> crates in the winapi family should be removed, and all imports updated to point towards <code class="highlighter-rouge">winapi</code> itself.</p>
<p>All of the <code class="highlighter-rouge">-sys</code> crates on <code class="highlighter-rouge">crates.io</code> are now deprecated and may eventually be yanked in the future to prevent new projects from accidentally using them. If you still have a project using these, it will continue to work, but it’s highly recommended you migrate to <code class="highlighter-rouge">winapi</code> 0.3 when possible to take advantage of the various improvements and gain access to new bindings.</p>
<h2 id="items-are-now-organised-into-modules">Items are now organised into modules.</h2>
<p>Definitions in <code class="highlighter-rouge">winapi</code> were previously not organised into modules. This allowed you to use a type, or constant without having to consider where it was defined. If C code or documentation mentioned <code class="highlighter-rouge">HWND</code>, then it was available as <code class="highlighter-rouge">winapi::HWND</code>, irrespective of the C header required.</p>
<p>In 0.3, all items are organised into modules based on the Windows SDK header file that defines them. [<a href="#fn†">†</a>] If you are familiar with the file structure of the Windows SDK headers, <code class="highlighter-rouge">winapi</code> now directly mirrors that. For example, <code class="highlighter-rouge">HWND</code> is now located at <code class="highlighter-rouge">shared::windef::HWND</code>. To continue the previous example, <code class="highlighter-rouge">MessageBoxW</code>, which is defined by <code class="highlighter-rouge">winuser.h</code>, can now be found in the <code class="highlighter-rouge">um::winuser</code> module.</p>
<p>You can determine where an item (or the module that corresponds to a particular header) is located by searching the <a href="https://docs.rs/winapi/0.3/x86_64-pc-windows-msvc/winapi/">online <code class="highlighter-rouge">winapi</code> 0.3 documentation</a>. Most translated headers will be in the <code class="highlighter-rouge">um</code> (user-mode) top-level module, items shared between user- and kernel-mode code in the <code class="highlighter-rouge">shared</code> module, Visual C++-specific items in the <code class="highlighter-rouge">vc</code> module, and WinRT-related items in the <code class="highlighter-rouge">winrt</code> module.</p>
<p>If given a choice between using names from both <code class="highlighter-rouge">shared</code> and <code class="highlighter-rouge">um</code> (as the latter re-exports items from the former), and you are not writing code intended to run in the kernel (<em>i.e.</em> device drivers), stick to <code class="highlighter-rouge">um</code>. There is no difference between the two, but using the <code class="highlighter-rouge">um</code> modules better matches the conventions of writing user-mode code.</p>
<h2 id="modules-gated-on-feature-flags">Modules gated on feature flags</h2>
<p>All binding modules are gated behind Cargo feature flags. This means that in order to access the contents of a module, you must first enable the corresponding feature flag on the <code class="highlighter-rouge">winapi</code> crate. For example, to use <code class="highlighter-rouge">MessageBoxW</code> in the <code class="highlighter-rouge">um::winuser</code> module, you must enable the <code class="highlighter-rouge">winuser</code> feature.</p>
<p>Note that enabling a module <em>also</em> enables any modules it depends on for types. For example, <code class="highlighter-rouge">MessageBoxW</code>’s definition requires <code class="highlighter-rouge">HWND</code>. As a result, enabling the <code class="highlighter-rouge">winuser</code> feature <em>also</em> enables (among others) the <code class="highlighter-rouge">windef</code> feature, so that <code class="highlighter-rouge">HWND</code> is defined.</p>
<p>Features also control which DLLs will be linked. Enabling a module will automatically link any libraries needed by functions defined in that module. For example, enabling <code class="highlighter-rouge">winuser</code> will automatically cause your program to be linked against <code class="highlighter-rouge">user32.lib</code>, resulting in a runtime dependency on <code class="highlighter-rouge">user32.dll</code>.</p>
<p>There is also an <code class="highlighter-rouge">everything</code> feature that enables all other feature gates. Enabling everything will adversely affect compile times. [<a href="#fn‡">‡</a>]</p>
<h2 id="compile-time-improvements">Compile time improvements</h2>
<p>One of the biggest complaints about 0.2 was compile times. Due to <code class="highlighter-rouge">winapi</code> being such a common dependency on Windows, users would often find their builds waiting on <code class="highlighter-rouge">winapi</code> before cargo could move on to compiling the rest of their project. Given that <code class="highlighter-rouge">winapi</code> is still tiny compared to the sheer amount of definitions in the Windows SDK, something had to be done to improve compile times.</p>
<p>Thanks to a lot of hard work optimizing the way symbols are defined, compile times have dropped significantly. Despite 0.3.0 having over twice as much code as 0.2.8, compile times have dropped from 23 seconds to 18 seconds with all features enabled.</p>
<p>However, if you only enable the features that you need, compile times drop to almost negligible levels. For example if you just enable the <code class="highlighter-rouge">winuser</code> feature, it will take less than 4 seconds to compile. Because modules are disabled by default, as new headers are added to <code class="highlighter-rouge">winapi</code> your compile time will remain constant!</p>
<h2 id="com-interfaces">COM interfaces</h2>
<p>All COM interfaces now implement the <code class="highlighter-rouge">Interface</code> trait, which will allow better <code class="highlighter-rouge">ComPtr</code> abstractions. Currently this trait exposes a single method which returns the IID of the interface, essential for <code class="highlighter-rouge">QueryInterface</code> wrappers. For example, to get the IID of the <code class="highlighter-rouge">IUnknown</code> interface, call <code class="highlighter-rouge">IUnknown::uuidof()</code>.</p>
<h2 id="enumerations">Enumerations</h2>
<p>Previously, each <code class="highlighter-rouge">enum</code> was translated to a “newtype” structure. For example, the definition of <code class="highlighter-rouge">POINTER_INPUT_TYPE</code> in <code class="highlighter-rouge">winapi</code> 0.2 was equivalent to:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">pub</span> <span class="k">struct</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="k">pub</span> <span class="nb">u32</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_POINTER</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="mi">0x00000001</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_TOUCH</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="mi">0x00000002</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_PEN</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="mi">0x00000003</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_MOUSE</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="mi">0x00000004</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_TOUCHPAD</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nf">POINTER_INPUT_TYPE</span><span class="p">(</span><span class="mi">0x00000005</span><span class="p">);</span>
</code></pre></div></div>
<p>For <code class="highlighter-rouge">winapi</code> 0.3, enumerations are instead type aliases to the underlying integer type. The primary reason for this is compile time improvements, due to fewer types and significantly fewer trait implementations being produced. The equivalent to the above in 0.3 is:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">pub</span> <span class="k">type</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="nb">u32</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_POINTER</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="mi">0x00000001</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_TOUCH</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="mi">0x00000002</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_PEN</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="mi">0x00000003</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_MOUSE</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="mi">0x00000004</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">const</span> <span class="n">PT_TOUCHPAD</span><span class="p">:</span> <span class="n">POINTER_INPUT_TYPE</span> <span class="o">=</span> <span class="mi">0x00000005</span><span class="p">;</span>
</code></pre></div></div>
<h2 id="unions">Unions</h2>
<p>The way unions are handled has changed. Previously, <code class="highlighter-rouge">winapi</code> generated methods for types that <em>contained</em> unions, with a pair of methods per union field. These methods would access a “backing field” stored in the host structure.</p>
<p>For example, in 0.2, the <code class="highlighter-rouge">INPUT</code> structure for x86-64 was roughly equivalent to:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">#</span><span class="p">[</span><span class="nf">cfg</span><span class="p">(</span><span class="n">target_arch</span> <span class="o">=</span> <span class="s">"x86_64"</span><span class="p">)]</span>
<span class="k">struct</span> <span class="n">INPUT</span> <span class="p">{</span>
<span class="k">pub</span> <span class="n">type_</span><span class="p">:</span> <span class="p">::</span><span class="n">DWORD</span><span class="p">,</span>
<span class="k">pub</span> <span class="n">u</span><span class="p">:</span> <span class="p">[</span><span class="nb">u64</span><span class="p">;</span> <span class="mi">4</span><span class="p">],</span>
<span class="p">}</span>
<span class="k">impl</span> <span class="n">INPUT</span> <span class="p">{</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">mi</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">MOUSEINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">ki</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">KEYBDINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">hi</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">HARDWAREINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">mi_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">MOUSEINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">ki_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">KEYBDINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">hi_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">HARDWAREINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="py">.u</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
<span class="c">/// Access the `mi` field of an `INPUT`.</span>
<span class="k">fn</span> <span class="nf">input_mi</span><span class="p">(</span><span class="n">inp</span><span class="p">:</span> <span class="o">&</span><span class="n">INPUT</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">MOUSEINPUT</span> <span class="p">{</span>
<span class="n">inp</span><span class="nf">.mi</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In 0.3, unions are now represented as a distinct type, with the methods defined on said union types, rather than on the host structure types. The 0.3 equivalent to the above is:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">INPUT</span> <span class="p">{</span>
<span class="k">pub</span> <span class="n">type_</span><span class="p">:</span> <span class="n">DWORD</span><span class="p">,</span>
<span class="k">pub</span> <span class="n">u</span><span class="p">:</span> <span class="n">INPUT_u</span><span class="p">,</span>
<span class="p">}</span>
<span class="nd">#[cfg(target_arch</span> <span class="nd">=</span> <span class="s">"x86_64"</span><span class="nd">)]</span>
<span class="k">pub</span> <span class="k">struct</span> <span class="nf">INPUT_u</span><span class="p">([</span><span class="nb">u64</span><span class="p">;</span> <span class="mi">4</span><span class="p">]);</span>
<span class="k">impl</span> <span class="n">INPUT_u</span> <span class="p">{</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">mi</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">MOUSEINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">ki</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">KEYBDINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">hi</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">HARDWAREINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">mi_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">MOUSEINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">ki_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">KEYBDINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="k">pub</span> <span class="k">unsafe</span> <span class="k">fn</span> <span class="nf">hi_mut</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="k">mut</span> <span class="n">HARDWAREINPUT</span> <span class="p">{</span> <span class="nf">transmute</span><span class="p">(</span><span class="k">self</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
<span class="c">/// Access the `mi` field of an `INPUT`.</span>
<span class="k">fn</span> <span class="nf">input_mi</span><span class="p">(</span><span class="n">inp</span><span class="p">:</span> <span class="o">&</span><span class="n">INPUT</span><span class="p">)</span> <span class="k">-></span> <span class="o">&</span><span class="n">MOUSEINPUT</span> <span class="p">{</span>
<span class="n">inp</span><span class="py">.u</span><span class="nf">.mi</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Note that code which accessed union members needs to be modified.</p>
<p>This change was made to bring <code class="highlighter-rouge">winapi</code> unions more in line with language-level unions (stabilised in Rust 1.19). Although <code class="highlighter-rouge">winapi</code> 0.3 does not use these native unions (in order to support older versions of Rust), the next semver-incompatible version of <code class="highlighter-rouge">winapi</code> <em>will</em> switch to native unions.</p>
<p>Finally, the explicit guidance now is to initialise union types with <a href="https://doc.rust-lang.org/std/mem/fn.zeroed.html"><code class="highlighter-rouge">mem::zeroed</code></a>. Again, this is to ease the future transition to native unions.</p>
<h2 id="standard-library-support-and-c_void">Standard library support and <code class="highlighter-rouge">c_void</code>.</h2>
<p><code class="highlighter-rouge">winapi</code> now defaults to <em>not</em> linking against the standard library. There is only one situation in which this will be a problem: when you wish to use <code class="highlighter-rouge">winapi</code> definitions with other code that uses the <code class="highlighter-rouge">c_void</code> type.</p>
<p><code class="highlighter-rouge">winapi</code> defines a number of C-compatible types in the top-level <code class="highlighter-rouge">ctypes</code> module. All of these are aliases to the “real” type (<em>e.g.</em> <code class="highlighter-rouge">type c_char = i8;</code>). The exception is <code class="highlighter-rouge">c_void</code> which does not have a single, corresponding Rust type. As such, by default, <code class="highlighter-rouge">winapi</code> defines its own <code class="highlighter-rouge">c_void</code> type.</p>
<p>However, this <code class="highlighter-rouge">c_void</code> will not be compatible with <code class="highlighter-rouge">c_void</code> as used by any other code, unless that code is specifically using <code class="highlighter-rouge">winapi</code>’s type. This can be fixed by enabling the <code class="highlighter-rouge">std</code> feature, which causes <code class="highlighter-rouge">winapi::ctypes::c_void</code> to instead alias to <code class="highlighter-rouge">std::os::raw::c_void</code>.</p>
<h2 id="mingw-import-libraries">MinGW import libraries</h2>
<p>One of the strange things about the <code class="highlighter-rouge">pc-windows-gnu</code> targets is the fact that it is a self contained toolchain capable of linking Rust projects without any external compilers installed. Unfortunately it only comes with a small selection of import libraries, which meant many system functions would not link by default.</p>
<p>The various <code class="highlighter-rouge">-sys</code> crates from the 0.2 era solved this by bundling import libraries from MinGW-w64, however this was a poor solution as those import libraries were woefully out of date, meaning you still could not use any functions introduced with newer versions of Windows. Furthermore, even if you only used the <code class="highlighter-rouge">pc-windows-msvc</code> targets, you would still waste a bit of bandwidth downloading these bundled import libraries.</p>
<p>In 0.3 all these import libraries were moved to dedicated import library crates, <code class="highlighter-rouge">winapi-x86_64-pc-windows-gnu</code> and <code class="highlighter-rouge">winapi-i686-pc-windows-gnu</code>, which <code class="highlighter-rouge">winapi</code> has target specific dependencies on in order to prevent cargo from downloading them on targets that don’t need them. In addition, these import libraries are made by me and are up to date with the latest Windows SDK, allowing you to use the hottest new Windows 10 functionality.</p>
<h2 id="migration-example">Migration example</h2>
<p>To make it easier to understand how to migrate your code, here is a simple “Hello, world!” example.</p>
<p>In <code class="highlighter-rouge">winapi</code> 0.2 you would have something like the following:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">//! Add the following to `Cargo.toml`:</span>
<span class="c">//!</span>
<span class="c">//! ```cargo</span>
<span class="c">//! [dependencies]</span>
<span class="c">//! winapi = "0.2"</span>
<span class="c">//! user32-sys = "0.2"</span>
<span class="c">//! ```</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">winapi</span><span class="p">;</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">user32</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="n">Error</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">print_message</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="k">-></span> <span class="n">Result</span><span class="o"><</span><span class="nb">i32</span><span class="p">,</span> <span class="n">Error</span><span class="o">></span> <span class="p">{</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">ffi</span><span class="p">::</span><span class="n">OsStr</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">iter</span><span class="p">::</span><span class="n">once</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">os</span><span class="p">::</span><span class="nn">windows</span><span class="p">::</span><span class="nn">ffi</span><span class="p">::</span><span class="n">OsStrExt</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">ptr</span><span class="p">::</span><span class="n">null_mut</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">winapi</span><span class="p">::</span><span class="n">MB_OK</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">user32</span><span class="p">::</span><span class="n">MessageBoxW</span><span class="p">;</span>
<span class="k">let</span> <span class="n">wide</span><span class="p">:</span> <span class="nb">Vec</span><span class="o"><</span><span class="nb">u16</span><span class="o">></span> <span class="o">=</span> <span class="nn">OsStr</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span><span class="nf">.encode_wide</span><span class="p">()</span><span class="nf">.chain</span><span class="p">(</span><span class="nf">once</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span><span class="nf">.collect</span><span class="p">();</span>
<span class="k">let</span> <span class="n">ret</span> <span class="o">=</span> <span class="k">unsafe</span> <span class="p">{</span>
<span class="nf">MessageBoxW</span><span class="p">(</span><span class="nf">null_mut</span><span class="p">(),</span> <span class="n">wide</span><span class="nf">.as_ptr</span><span class="p">(),</span> <span class="n">wide</span><span class="nf">.as_ptr</span><span class="p">(),</span> <span class="n">MB_OK</span><span class="p">)</span>
<span class="p">};</span>
<span class="k">if</span> <span class="n">ret</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span> <span class="nf">Err</span><span class="p">(</span><span class="nn">Error</span><span class="p">::</span><span class="nf">last_os_error</span><span class="p">())</span> <span class="p">}</span>
<span class="k">else</span> <span class="p">{</span> <span class="nf">Ok</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nf">print_message</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>With <code class="highlighter-rouge">winapi</code> 0.3 your code would be changed to this:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">//! Add the following to `Cargo.toml`:</span>
<span class="c">//!</span>
<span class="c">//! ```cargo</span>
<span class="c">//! [dependencies.winapi]</span>
<span class="c">//! version = "0.3"</span>
<span class="c">//! features = ["winuser"] # enable the `um::winuser` module.</span>
<span class="c">//!</span>
<span class="c">//! # No dependency on `user32-sys`.</span>
<span class="c">//! ```</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">winapi</span><span class="p">;</span>
<span class="c">// No `extern crate user32;`.</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="n">Error</span><span class="p">;</span>
<span class="k">fn</span> <span class="nf">print_message</span><span class="p">(</span><span class="n">msg</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="k">-></span> <span class="n">Result</span><span class="o"><</span><span class="nb">i32</span><span class="p">,</span> <span class="n">Error</span><span class="o">></span> <span class="p">{</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">ffi</span><span class="p">::</span><span class="n">OsStr</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">iter</span><span class="p">::</span><span class="n">once</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">os</span><span class="p">::</span><span class="nn">windows</span><span class="p">::</span><span class="nn">ffi</span><span class="p">::</span><span class="n">OsStrExt</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">ptr</span><span class="p">::</span><span class="n">null_mut</span><span class="p">;</span>
<span class="c">// `MB_OK` and `MessageBoxW` are in a module.</span>
<span class="k">use</span> <span class="nn">winapi</span><span class="p">::</span><span class="nn">um</span><span class="p">::</span><span class="nn">winuser</span><span class="p">::{</span><span class="n">MB_OK</span><span class="p">,</span> <span class="n">MessageBoxW</span><span class="p">};</span>
<span class="k">let</span> <span class="n">wide</span><span class="p">:</span> <span class="nb">Vec</span><span class="o"><</span><span class="nb">u16</span><span class="o">></span> <span class="o">=</span> <span class="nn">OsStr</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span><span class="nf">.encode_wide</span><span class="p">()</span><span class="nf">.chain</span><span class="p">(</span><span class="nf">once</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span><span class="nf">.collect</span><span class="p">();</span>
<span class="k">let</span> <span class="n">ret</span> <span class="o">=</span> <span class="k">unsafe</span> <span class="p">{</span>
<span class="nf">MessageBoxW</span><span class="p">(</span><span class="nf">null_mut</span><span class="p">(),</span> <span class="n">wide</span><span class="nf">.as_ptr</span><span class="p">(),</span> <span class="n">wide</span><span class="nf">.as_ptr</span><span class="p">(),</span> <span class="n">MB_OK</span><span class="p">)</span>
<span class="p">};</span>
<span class="k">if</span> <span class="n">ret</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span> <span class="nf">Err</span><span class="p">(</span><span class="nn">Error</span><span class="p">::</span><span class="nf">last_os_error</span><span class="p">())</span> <span class="p">}</span>
<span class="k">else</span> <span class="p">{</span> <span class="nf">Ok</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nf">print_message</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<hr />
<p><a name="fn†"></a>
[†]: This is due to the existence of duplicate, non-compatible definitions in the Windows SDK. The SDK gets around this via abuse of the C pre-processor to redefine names based on the order in which header files are included.</p>
<p><a name="fn‡"></a>
[‡]: You will not just have time to make a cup of coffee. You will have time to fly to the coffee belt, harvest the beans, fly back, roast them, grind them, and <em>then</em> make a cup of coffee.</p>For over a year people have been wondering when the next version of winapi would be published, and today I am happy to announce that winapi 0.3 has finally been published to crates.io! This new version has a lot of changes, so this post will go over them and cover any changes that will need to be made to your own code when migrating to this new version.boop2016-12-26T00:00:00+00:002016-12-26T00:00:00+00:00https://retep998.github.io/blog/New-Blog<p>Today I have decided to finally start a blog where I will ramble about stuff. It’ll probably be interesting.</p>
<p>There’s currently a severe lack of bunnies on the blog, but hopefully that situation will improve in the near future.</p>Today I have decided to finally start a blog where I will ramble about stuff. It’ll probably be interesting.