<p dir="auto">Usually C bindings requires different calling conventions per platform. For example, linux-32 usually uses cdecl, win-32 uses stdcall, and win-64 uses win64-specific convention.<br>
So if we want to bind a function universally, we have to duplicate <code class="notranslate">extern ... {}</code> block for each platform, e.g.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#[cfg(target_os = &quot;linux&quot;)]
extern &quot;cdecl&quot; {
    fn func();
    ...
}
#[cfg(target_os = &quot;win32&quot;, target_arch = &quot;x86&quot;)]
extern &quot;stdcall&quot; {
    fn func();
    ...
}
#[cfg(target_os = &quot;win32&quot;, target_arch = &quot;x86_64&quot;)]
extern { // this is identical to extern &quot;C&quot; or extern &quot;cdecl&quot;
    fn func();
    ...
}"><pre class="notranslate"><span class="pl-c1">#<span class="pl-kos">[</span>cfg<span class="pl-kos">(</span>target_os = <span class="pl-s">"linux"</span><span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">extern</span> <span class="pl-s">"cdecl"</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">func</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    ...
<span class="pl-kos">}</span>
<span class="pl-c1">#<span class="pl-kos">[</span>cfg<span class="pl-kos">(</span>target_os = <span class="pl-s">"win32"</span><span class="pl-kos">,</span> target_arch = <span class="pl-s">"x86"</span><span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">extern</span> <span class="pl-s">"stdcall"</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">func</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    ...
<span class="pl-kos">}</span>
<span class="pl-c1">#<span class="pl-kos">[</span>cfg<span class="pl-kos">(</span>target_os = <span class="pl-s">"win32"</span><span class="pl-kos">,</span> target_arch = <span class="pl-s">"x86_64"</span><span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">extern</span> <span class="pl-kos">{</span> <span class="pl-c">// this is identical to extern "C" or extern "cdecl"</span>
    <span class="pl-k">fn</span> <span class="pl-en">func</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    ...
<span class="pl-kos">}</span></pre></div>
<p dir="auto">which is inconvenient and fragile. (I actually copied <a href="https://github.com/klutzy/rust/blob/1f831d9637232805d6fb82f6f1c8b6869e066860/src/libstd/libc.rs#L3127">large extern blob</a> for Mingw-w64 support (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="17980306" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/8488" data-hovercard-type="pull_request" data-hovercard-url="/rust-lang/rust/pull/8488/hovercard" href="https://github.com/rust-lang/rust/pull/8488">#8488</a>).)</p>
<p dir="auto">Other option is to generate binding code per platform from template. <a href="https://github.com/lifthrasiir/rust-opengles-angle">lifthrasiir/rust-opengles-angle</a> uses the approach for egl binding.</p>
<p dir="auto">I think it's good to add default calling convention keyword e.g. "platform" so that</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="extern &quot;platform&quot; {
    fn func();
    ...
}"><pre class="notranslate"><span class="pl-k">extern</span> <span class="pl-s">"platform"</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">func</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    ...
<span class="pl-kos">}</span></pre></div>
<p dir="auto">where "platform" is interpreted as cdecl for linux-32, stdcall for win32, and so on. It would solve the issue for most cases.</p>
<p dir="auto">EDIT: in irc <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/luqmana/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/luqmana">@luqmana</a> suggested to change <code class="notranslate">extern {}</code> (no abi specified) as platform-native callconv. (It's currently interpreted as "cdecl".) I think it's the best option.</p>
<p dir="auto">Consider code like this (<a href="http://is.gd/PxabmK" rel="nofollow">playpen</a>):</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="fn add3&lt;T&gt;(x: i32) -&gt; i32 { x + 3 }

fn main() {
    println!(&quot;add3(4): {}&quot;, add3(4));
}"><pre class="notranslate"><span class="pl-k">fn</span> <span class="pl-en">add3</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">x</span><span class="pl-kos">:</span> <span class="pl-smi">i32</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">i32</span> <span class="pl-kos">{</span> x + <span class="pl-c1">3</span> <span class="pl-kos">}</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"add3(4): {}"</span>, add3<span class="pl-kos">(</span><span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The Rust compiler currently rejects the above, because it cannot infer what type to assign to the type parameter <code class="notranslate">T</code> in the above invocation <code class="notranslate">add3(4)</code>.</p>
<p dir="auto">The problematic thing is the message:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;anon&gt;:4:29: 4:33 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
&lt;anon&gt;:4     println!(&quot;add3(4): {}&quot;, add3(4));
                                     ^~~~"><pre class="notranslate"><code class="notranslate">&lt;anon&gt;:4:29: 4:33 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
&lt;anon&gt;:4     println!("add3(4): {}", add3(4));
                                     ^~~~
</code></pre></div>
<ol dir="auto">
<li>This message complains about <code class="notranslate">_</code>, rather than referencing the parameter <code class="notranslate">T</code> of <code class="notranslate">fn add3</code>.</li>
<li>It might be nice if, when we encounter this error, if we also did an additional check for the function itself and see if the type parameter in question is unused in the signature of <code class="notranslate">fn add</code> (since in such a situation, there is no way that the callsite will be able to supply the information via type annotation -- the only option is the generic parameter binding form like <code class="notranslate">add3::&lt;(f64,i8)&gt;(4)</code>, and it is <em>likely</em> (though not assured) that the actual bug is in the definition of <code class="notranslate">fn add3</code> itself, rather than at the call site.</li>
</ol>