一生痴爱美景 發表於 2019-10-31 20:34:00

C#如何调用C++(基础篇)

<p>闲暇之余,记一下笔记!记录一下c#如何调用C++的动态库(dll).</p>
<p>步骤:</p>
<h2><strong>一、创建一个C++类,例如:</strong></h2>
<p><br>AddOperate.h</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">extern</span> _declspec(dllexport) <span style="color: rgba(0, 0, 255, 1)">int</span> Sum(<span style="color: rgba(0, 0, 255, 1)">int</span> a, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> b);
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AddOperate
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> :
};</span></pre>
</div>
<p>AddOperate.cpp</p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AddOperate.h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">iostream</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> std;

</span><span style="color: rgba(0, 0, 255, 1)">int</span> Sum(<span style="color: rgba(0, 0, 255, 1)">int</span> a, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> b)
{
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (a - (<span style="color: rgba(0, 0, 255, 1)">int</span>)a != <span style="color: rgba(128, 0, 128, 1)">0</span> || b - (<span style="color: rgba(0, 0, 255, 1)">int</span>)b != <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
      cout </span>&lt;&lt; <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请输入整数</span><span style="color: rgba(128, 0, 0, 1)">"</span> &lt;&lt;<span style="color: rgba(0, 0, 0, 1)"> endl;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> -<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> a +<span style="color: rgba(0, 0, 0, 1)"> b;
}</span></pre>
</div>
<p>&nbsp;</p>
<h2>2、将C++代码编译成动态库dll</h2>
<p>&nbsp;</p>
<p>需要设置编译配置:<br>A:项目--属性---赔指数型--常规---配置类型---动态库(.dll)</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031202731653-738321081.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;B:项目--属性--配置属性--C/C++---高级---编译为---便以为C++代码(/TP)</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031202802260-321936374.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;这个活动X64注意,调用放C#最好也用这个X64;</p>
<p>然后点击项目--生成,就会看到dll了;</p>
<h2><strong>3、将dll拷贝到c#项目输入目录,一般在bin/debug下面;</strong></h2>
<h2><strong>4、编写C#代码调用dll</strong></h2>
<div class="cnblogs_code">
<pre>
      </span><span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Sum(<span style="color: rgba(0, 0, 255, 1)">int</span> a, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> b);
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请输入NumberA:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">int</span> numberA =<span style="color: rgba(0, 0, 0, 1)"> Convert.ToInt32(Console.ReadLine());

                Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请输入NumberB:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">int</span> numberB =<span style="color: rgba(0, 0, 0, 1)"> Convert.ToInt32(Console.ReadLine());

                Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">the numberA is:{numberA};numberB is:{numberB},The Sum is:{Sum(numberA, numberB)}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
               
            }
            </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)">(Exception ex) {
                Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ex:{ex}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            }

            Console.ReadLine();
      }</span></pre>
</div>
<p>主要是这两行:</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031202932056-1030805086.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>这个“Sum”方法必须跟dll方法名字相同,否则找不到;</p>
<p>接下来看看运行结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031202957468-567423468.png" alt=""></p>
<p>很尴尬,提示找不到“Sum”方法,难道我们的操作有问题。</p>
<p>排查了很久,发现C++方法编译成dll时,方法名会改变,也是为了安全;</p>
<p>解决方案:</p>
<p>要把C++代码转化成C语言!</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031203052401-187972535.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;就这样,然后再编译dll过来,再次执行:</p>
<p>结果:成功</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031203125141-246420702.png" alt=""></p>
<p>&nbsp;</p>
<h2><strong>五、其他可能遇到的问题</strong></h2>
<p>A:对PInvoke函数的调用导致堆栈不对称问题</p>
<p>  方法定义加:CallingConvention = CallingConvention.Cdecl</p>
<p>B:未处理System.BadImageFormatException,试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)</p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201910/780812-20191031203303564-1298884112.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;就这样OK了!。</p>
<h2><strong>六:思考:如果这个dll中有多个方法需要调用,</strong></h2>
<p><strong>该怎么办,是否是这样,一个个声明引用??</strong></p>
<p><img src="https://img2018.cnblogs.com/blog/780812/201911/780812-20191101161146507-773742049.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;预知结果,请看下一篇文章:《C#如何调用C++(进阶篇)》,地址:https://www.cnblogs.com/skyfreedom/p/11783629.html</p>

</div>
<div id="MySignature" role="contentinfo">
    没有什么优雅的代码比空代码的执行效率更高<br><br>
来源:https://www.cnblogs.com/skyfreedom/p/11773597.html
頁: [1]
查看完整版本: C#如何调用C++(基础篇)