<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>C++ on LeafCxy's Blog</title><link>https://leafcxy.github.io/tags/c++/</link><description>Recent content in C++ on LeafCxy's Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 22 Jul 2025 01:15:46 +0000</lastBuildDate><atom:link href="https://leafcxy.github.io/tags/c++/index.xml" rel="self" type="application/rss+xml"/><item><title>csharp互操作</title><link>https://leafcxy.github.io/posts/2025-07-22-1/</link><pubDate>Tue, 22 Jul 2025 01:15:46 +0000</pubDate><guid>https://leafcxy.github.io/posts/2025-07-22-1/</guid><description>&lt;h2 id="platform-invokepinvoke即平台调用主要用于调用c库函数和windows-api"&gt;Platform Invoke(P/Invoke)，即平台调用,主要用于调用C库函数和Windows API&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; System;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用平台调用技术进行互操作性之前，首先需要添加这个命名空间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; System.Runtime.InteropServices;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;平台调用&lt;/span&gt;Demo
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在托管代码中对非托管函数进行声明，并且附加平台调用所需要属性&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在默认情况下，CharSet为CharSet.Ansi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 指定调用哪个版本的方法有两种——通过DllImport属性的CharSet字段和通过EntryPoint字段指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在托管函数中声明注意一定要加上 static 和extern 这两个关键字 [DllImport(&amp;#34;user32.dll&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBox1(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在默认情况下，CharSet为CharSet.Ansi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [DllImport(&amp;#34;user32.dll&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBoxA(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在默认情况下，CharSet为CharSet.Ansi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [DllImport(&amp;#34;user32.dll&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBox(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 第一种指定方式，通过CharSet字段指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [DllImport(&amp;#34;user32.dll&amp;#34;, CharSet = CharSet.Unicode)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBox2(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 通过EntryPoint字段指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [DllImport(&amp;#34;user32.dll&amp;#34;, EntryPoint=&amp;#34;MessageBoxA&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBox3(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; [DllImport(&amp;#34;user32.dll&amp;#34;, EntryPoint = &amp;#34;MessageBoxW&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extern&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; MessageBox4(IntPtr hWnd, String text, String caption, &lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Main(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 在托管代码中直接调用声明的托管函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 使用CharSet字段指定的方式，要求在托管代码中声明的函数名必须与非托管函数名一样&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 否则就会出现找不到入口点的运行时错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//MessageBox1(new IntPtr(0), &amp;#34;Learning Hard&amp;#34;, &amp;#34;欢迎&amp;#34;, 0);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 下面的调用都可以运行正确&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//MessageBoxA(new IntPtr(0), &amp;#34;Learning Hard&amp;#34;, &amp;#34;欢迎&amp;#34;, 0);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//MessageBox(new IntPtr(0), &amp;#34;Learning Hard&amp;#34;, &amp;#34;欢迎&amp;#34;, 0);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 使用指定函数入口点的方式调用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//MessageBox3(new IntPtr(0), &amp;#34;Learning Hard&amp;#34;, &amp;#34;欢迎&amp;#34;, 0);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 调用Unicode版本的会出现乱码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MessageBox4(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; IntPtr(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;&amp;#34;Learning Hard&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;欢迎&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- more --&gt;
&lt;h2 id="c-introp-主要用于managed-c托管c中调用c类库"&gt;C++ Introp, 主要用于Managed C++(托管C++)中调用C++类库&lt;/h2&gt;
&lt;p&gt;第二部分主要向大家介绍了第一种互操作性技术，然后我们也可以使用C++ Interop技术来实现与非托管代码进行交互。
然而C++ Interop 方式有一个与平台调用不一样的地方，就是C++ Interop 允许托管代码和非托管代码存在于一个程序集中，甚至同一个文件中。
C++ Interop 是在源代码上直接链接和编译非托管代码来实现与非托管代码进行互操作的，而平台调用是加载编译后生成的非托管DLL并查找函数的入口地址来实现与非托管函数进行互操作的。
&lt;code&gt;C++ Interop使用托管C++来包装非托管C++代码，然后编译生成程序集，然后再托管代码中引用该程序集，从而来实现与非托管代码的互操作&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>不能在控制元件上呼叫Invoke</title><link>https://leafcxy.github.io/posts/2025-07-22/</link><pubDate>Tue, 22 Jul 2025 01:13:36 +0000</pubDate><guid>https://leafcxy.github.io/posts/2025-07-22/</guid><description>&lt;p&gt;在Window窗體程式開發的時候，如果使用多執行緒程式設計，在子執行緒中訪問主執行緒窗體內的控制元件，就需要使用控制元件的Control.Invoke方法或者BeginInvoke方法。但是有時候因為Window執行速度太快，尤其是你寫程式碼的時候在InitializeComponent();完成之前起了一個執行緒去執行某些操作，涉及到窗體控制元件的，當你在呼叫Control.Invoke的時候，就可能出現 “在建立視窗控制代碼之前，不能在控制元件上呼叫 Invoke 或 BeginInvoke&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;解決的辦法就是讓執行緒等待，直到視窗控制代碼建立完畢：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (!&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.IsHandleCreated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.BeginInvoke(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ProListIndexChangedDelegate(GetProLyric));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//根據不同情況也可以： &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.IsHandleCreated)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BeginInvoke(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ProListIndexChangedDelegate(GetProLyric));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有一個更巧妙的方法，只要在BeginInvoke方法的呼叫語句前再加一句：IntPtr i = this.Handle;就OK了，這比死迴圈配合this.IsHandleCreated的判斷方法更簡潔，因為this.Handle這個屬性本身就對應一個方法，取不到控制代碼，程式就不會向下進行。&lt;/p&gt;</description></item></channel></rss>