< > >强> C++:< /强> </p>
<p>我刚刚遇到了同样的问题,我认为值得一提的是,当同时使用<code>__stdcall</code>(或<code>WINAPI</code><strong>和</strong><code>extern "C"</code>时,会出现一个问题:</p>
<p>如您所知<code>extern "C"</code>移除装饰,以代替:</p>
<pre><code>__declspec(dllexport) int Test(void) --> dumpbin : ?Test@@YaHXZ
</code></pre>
<p>您将获得一个未装饰的符号名称:</p>
<pre><code>extern "C" __declspec(dllexport) int Test(void) --> dumpbin : Test
</code></pre>
<p>但是<code>_stdcall</code>(=宏WINAPI,它改变了调用约定)也修饰了名称,因此如果我们同时使用这两个名称,我们可以获得:</p>
<pre><code> extern "C" __declspec(dllexport) int WINAPI Test(void) --> dumpbin : _Test@0
</code></pre>
<p>而且<code>extern "C"</code>的好处也失去了,因为符号被修饰(用@bytes)</p>
<blockquote>
<p>Note that this <em>only</em> occurs for x86 architecture because
the <code>__stdcall</code> convention is ignored on x64 (<a href="https://msdn.microsoft.com/en-us/library/zxk0tw93.aspx" rel="noreferrer">msdn</a> : <em>on x64 architectures, by convention, arguments are passed in registers when possible, and subsequent arguments are passed on the stack</em>.).</p>
</blockquote>
<p>如果同时针对x86和x64平台,这一点尤其棘手</p>
<hr/>
<p><strong>两种解决方案</strong></p>
<ol>
<li><p>使用定义文件。但这会迫使您维护def文件的状态</p></li>
<li><p>最简单的方法:定义宏(请参见<a href="https://msdn.microsoft.com/en-us/library/7f0aews7.aspx" rel="noreferrer">msdn</a>):</p></li>
</ol>
<blockquote>
<p>#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "="
__FUNCDNAME__)</p>
</blockquote>
<p>然后在函数体中包含以下pragma:</p>
<pre><code>#pragma EXPORT
</code></pre>
<p>完整示例:</p>
<pre><code> int WINAPI Test(void)
{
#pragma EXPORT
return 1;
}
</code></pre>
<p>这将导出x86和x64目标的未修饰函数,同时保留x86的<code>__stdcall</code>约定。在这种情况下<code>__declspec(dllexport)</code><strong>不是必需的</p>