<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>HuiHut</title>
  
  <subtitle>专业修电脑，副业补衣服。</subtitle>
  <link href="https://blog.huihut.com/atom.xml" rel="self"/>
  
  <link href="https://blog.huihut.com/"/>
  <updated>2023-11-03T14:37:05.670Z</updated>
  <id>https://blog.huihut.com/</id>
  
  <author>
    <name>huihut</name>
    
  </author>
  <follow_challenge>
    <feedId>89322862701642752</feedId>
    <userId>9nQZ_Xx2F97lT9yalOhlD</userId>
  </follow_challenge>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Log4cplus 日志库</title>
    <link href="https://blog.huihut.com/2020/11/22/Log4cplusLogLibrary/"/>
    <id>https://blog.huihut.com/2020/11/22/Log4cplusLogLibrary/</id>
    <published>2020-11-21T18:00:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Log4cplus 是 log4j 的 C++ 实现，其接口和使用逻辑与 log4j 基本保持一致。</p><ul><li>log4cplus 具有线程安全、灵活、以及多粒度控制的特点</li><li>可以通过将日志划分优先级使其可以面向程序调试、运行、测试、和维护等全生命周期</li><li>可以选择将日志输出到控制台、调试器、文件、服务器</li><li>可以通过指定策略对日志进行定期备份</li></ul><span id="more"></span><h2 id="许可协议"><a href="#许可协议" class="headerlink" title="许可协议"></a>许可协议</h2><p>Log4cplus 的每个文件是使用二级BSD许可协议（Two clause BSD license）或者 Apache license 2.0 许可协议，其中的线程池（ThreadPool.h）又是使用另外的协议。</p><h2 id="重要组成"><a href="#重要组成" class="headerlink" title="重要组成"></a>重要组成</h2><table><thead><tr><th>类</th><th>说明</th></tr></thead><tbody><tr><td>Filter</td><td>过滤器，过滤输出消息</td></tr><tr><td>Layout</td><td>布局器，控制输出消息的格式</td></tr><tr><td>Appender</td><td>附加器，将日志输出到所附加的设备终端如控制台、调试器、文件、远程服务器等等</td></tr><tr><td>Logger</td><td>记录器，保存并跟踪对象日志信息变更的实体，当你需要对一个对象进行记录时，就需要生成一个logger</td></tr><tr><td>Hierarchy</td><td>分类器，层次化的树型结构，用于对被记录信息的分类，层次中每一个节点维护一个logger的所有信息</td></tr><tr><td>LogLevel</td><td>优先权，包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL</td></tr></tbody></table><h3 id="关系"><a href="#关系" class="headerlink" title="关系"></a>关系</h3><ul><li>Hierarchy -&gt; Logger -&gt; Appender(Layout) -&gt; Filter</li><li>InternalLoggingEvent -&gt; LogLevel</li></ul><h2 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h2><h3 id="Filter"><a href="#Filter" class="headerlink" title="Filter"></a>Filter</h3><p>过滤器，用于过滤日志项，可继承Filter自定义过滤器，也可用自带的过滤器</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/log4cplus-filter.png"></p><ul><li>Filter</li><li>DenyAllFilter：全部过滤</li><li>LogLevelMatchFilter：等级过滤</li><li>LogLevelRangeFilter：等级范围过滤</li><li>StringMatchFilter：字符串过滤</li><li>FunctionFilter：方法函数过滤</li><li>NDCMatchFilter</li><li>MDCMatchFilter</li></ul><h3 id="Layout"><a href="#Layout" class="headerlink" title="Layout"></a>Layout</h3><p>布局器，控制输出日志消息的格式</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/log4cplus-layout.png"></p><ul><li>Layout</li><li>SimpleLayout: DEBUG - Hello world</li><li>TTCCLayout(time、thread、category、context)：[0x60004b030] INFO SlowObject &lt;Thread-0 loop&gt; - Actually doing something</li><li>PatternLayout</li></ul><h4 id="class-PatternLayout"><a href="#class-PatternLayout" class="headerlink" title="class PatternLayout"></a>class PatternLayout</h4><ul><li>%%a -- Abbreviated weekday name</li><li>%%A -- Full weekday name</li><li>%%b -- Abbreviated month name</li><li>%%B -- Full month name</li><li>%%c -- Standard date and time string</li><li>%%d -- Day of month as a decimal(1-31)</li><li>%%H -- Hour(0-23)</li><li>%%I -- Hour(1-12)</li><li>%%j -- Day of year as a decimal(1-366)</li><li>%%m -- Month as decimal(1-12)</li><li>%%M -- Minute as decimal(0-59)</li><li>%%p -- Locale's equivalent of AM or PM</li><li>%%q -- milliseconds as decimal(0-999) -- <b>Log4CPLUS specific</b><li>%%Q -- fractional milliseconds as decimal(0-999.999) -- <b>Log4CPLUS specific</b><li>%%S -- Second as decimal(0-59)</li><li>%%U -- Week of year, Sunday being first day(0-53)</li><li>%%w -- Weekday as a decimal(0-6, Sunday being 0)</li><li>%%W -- Week of year, Monday being first day(0-53)</li><li>%%x -- Standard date string</li><li>%%X -- Standard time string</li><li>%%y -- Year in decimal without century(0-99)</li><li>%%Y -- Year including century as decimal</li><li>%%Z -- Time zone name</li><li>%% -- The percent sign</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">PatternLayout</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;[%D&#123;%Y-%m-%d %H:%M:%S.%q&#125;] [%t] %-5p [%M] %m%n&quot;</span>));</span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[2020-08-24 01:30:43.650] [14168] DEBUG [main] <span class="built_in">log</span> <span class="built_in">test</span></span><br></pre></td></tr></table></figure><h3 id="Appender"><a href="#Appender" class="headerlink" title="Appender"></a>Appender</h3><p>附加器，将日志输出到所附加的设备终端如控制台、调试器、文件、远程服务器等等</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/log4cplus-appender.png"></p><h4 id="class-Appender"><a href="#class-Appender" class="headerlink" title="class Appender"></a>class Appender</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//! Asynchronous append.</span></span><br><span class="line"><span class="type">bool</span> async;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">log4cplus::helpers::Properties properties;</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;AsyncAppend&quot;</span>), <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;true&quot;</span>));</span><br></pre></td></tr></table></figure><h4 id="class-AsyncAppender"><a href="#class-AsyncAppender" class="headerlink" title="class AsyncAppender"></a>class AsyncAppender</h4><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/log4cplus-async-appender.png"></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">log4cplus::helpers::Properties properties;</span><br><span class="line"><span class="function">log4cplus::SharedAppenderPtr <span class="title">fileAppend</span><span class="params">(<span class="keyword">new</span> log4cplus::RollingFileAppender(properties))</span></span>;</span><br><span class="line"><span class="function">log4cplus::SharedAppenderPtr <span class="title">asyncAppender</span><span class="params">(<span class="keyword">new</span> log4cplus::AsyncAppender(fileAppend, <span class="number">100</span>))</span></span>;</span><br><span class="line">m_logger.<span class="built_in">addAppender</span>(asyncAppender);</span><br></pre></td></tr></table></figure><h4 id="class-RollingFileAppender"><a href="#class-RollingFileAppender" class="headerlink" title="class RollingFileAppender"></a>class RollingFileAppender</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">RollingFileAppender</span>(<span class="type">const</span> log4cplus::tstring&amp; filename,</span><br><span class="line">                    <span class="type">long</span> maxFileSize = <span class="number">10</span>*<span class="number">1024</span>*<span class="number">1024</span>,</span><br><span class="line">                    <span class="type">int</span> maxBackupIndex = <span class="number">1</span>,</span><br><span class="line">                    <span class="type">bool</span> immediateFlush = <span class="literal">true</span>,</span><br><span class="line">                    <span class="type">bool</span> createDirs = <span class="literal">false</span>);</span><br><span class="line"><span class="built_in">RollingFileAppender</span>(<span class="type">const</span> log4cplus::helpers::Properties&amp; properties);</span><br></pre></td></tr></table></figure><h3 id="Logger"><a href="#Logger" class="headerlink" title="Logger"></a>Logger</h3><p>记录器，保存并跟踪对象日志信息变更的实体，当你需要对一个对象进行记录时，就需要生成一个logger</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/log4cplus-logger.png"></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">log</span><span class="params">(LogLevel ll, <span class="type">const</span> log4cplus::tstring&amp; message,</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> <span class="type">char</span>* file = LOG4CPLUS_CALLER_FILE (),</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">int</span> line = LOG4CPLUS_CALLER_LINE (),</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> <span class="type">char</span>* function = LOG4CPLUS_CALLER_FUNCTION ())</span> <span class="type">const</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">log</span><span class="params">(spi::InternalLoggingEvent <span class="type">const</span> &amp;)</span> <span class="type">const</span></span>;</span><br><span class="line">        </span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">forcedLog</span><span class="params">(LogLevel ll, <span class="type">const</span> log4cplus::tstring&amp; message,</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> <span class="type">char</span>* file = LOG4CPLUS_CALLER_FILE (),</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">int</span> line = LOG4CPLUS_CALLER_LINE (),</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="type">const</span> <span class="type">char</span>* function = LOG4CPLUS_CALLER_FUNCTION ())</span> <span class="type">const</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">forcedLog</span><span class="params">(spi::InternalLoggingEvent <span class="type">const</span> &amp;)</span> <span class="type">const</span></span>;</span><br></pre></td></tr></table></figure><h3 id="Hierarchy"><a href="#Hierarchy" class="headerlink" title="Hierarchy"></a>Hierarchy</h3><p>分类器，层次化的树型结构，用于对被记录信息的分类，层次中每一个节点维护一个logger的所有信息</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> std::vector&lt;Logger&gt; ProvisionNode;</span><br><span class="line"><span class="keyword">typedef</span> std::map&lt;log4cplus::tstring, ProvisionNode&gt; ProvisionNodeMap;</span><br><span class="line"><span class="keyword">typedef</span> std::map&lt;log4cplus::tstring, Logger&gt; LoggerMap;</span><br><span class="line"></span><br><span class="line">ProvisionNodeMap provisionNodes;</span><br><span class="line">LoggerMap loggerPtrs;</span><br><span class="line">Logger root;</span><br></pre></td></tr></table></figure><h3 id="LogLevel"><a href="#LogLevel" class="headerlink" title="LogLevel"></a>LogLevel</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="type">int</span> LogLevel;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">const</span> LogLevel OFF_LOG_LEVEL     = <span class="number">60000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel FATAL_LOG_LEVEL   = <span class="number">50000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel ERROR_LOG_LEVEL   = <span class="number">40000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel WARN_LOG_LEVEL    = <span class="number">30000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel INFO_LOG_LEVEL    = <span class="number">20000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel DEBUG_LOG_LEVEL   = <span class="number">10000</span>;</span><br><span class="line"><span class="type">const</span> LogLevel TRACE_LOG_LEVEL   = <span class="number">0</span>;</span><br><span class="line"><span class="type">const</span> LogLevel ALL_LOG_LEVEL     = TRACE_LOG_LEVEL;</span><br><span class="line"><span class="type">const</span> LogLevel NOT_SET_LOG_LEVEL = <span class="number">-1</span>;</span><br></pre></td></tr></table></figure><h3 id="Properties"><a href="#Properties" class="headerlink" title="Properties"></a>Properties</h3><p>属性，用于配置参数</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">log4cplus::helpers::Properties properties;</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;File&quot;</span>), logFile.<span class="built_in">c_str</span>());</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;CreateDirs&quot;</span>), <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;true&quot;</span>));</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;ImmediateFlush&quot;</span>), <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;true&quot;</span>));</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;MaxFileSize&quot;</span>), std::<span class="built_in">to_wstring</span>(max_file_size).<span class="built_in">c_str</span>());</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;MaxBackupIndex&quot;</span>), std::<span class="built_in">to_wstring</span>(max_file_count).<span class="built_in">c_str</span>());</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;AsyncAppend&quot;</span>), s_async.<span class="built_in">c_str</span>());</span><br><span class="line">properties.<span class="built_in">setProperty</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Locale&quot;</span>), <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;en_US.UTF-8&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="function">log4cplus::SharedAppenderPtr <span class="title">fileAppend</span><span class="params">(<span class="keyword">new</span> log4cplus::RollingFileAppender(properties))</span></span>;</span><br></pre></td></tr></table></figure><h3 id="可变参数格式化打印日志"><a href="#可变参数格式化打印日志" class="headerlink" title="可变参数格式化打印日志"></a>可变参数格式化打印日志</h3><h4 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">LOG4CPLUS_INFO</span>(logger, <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Hello world&quot;</span>));</span><br></pre></td></tr></table></figure><h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><p>LOG4CPLUS_INFO_FMT</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> LOG4CPLUS_INFO_FMT(logger, ...)  \</span></span><br><span class="line"><span class="meta">    LOG4CPLUS_MACRO_FMT_BODY (logger, INFO_LOG_LEVEL, __VA_ARGS__)</span></span><br></pre></td></tr></table></figure><p>LOG4CPLUS_MACRO_FMT_BODY</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, ...)                 \</span></span><br><span class="line"><span class="meta">    LOG4CPLUS_SUPPRESS_DOWHILE_WARNING()                                \</span></span><br><span class="line"><span class="meta">    do &#123;                                                                \</span></span><br><span class="line"><span class="meta">        log4cplus::Logger const &amp; _l                                    \</span></span><br><span class="line"><span class="meta">            = log4cplus::detail::macros_get_logger (logger);            \</span></span><br><span class="line"><span class="meta">        <span class="keyword">if</span> (LOG4CPLUS_MACRO_LOGLEVEL_PRED (                             \</span></span><br><span class="line"><span class="meta">                _l.isEnabledFor (log4cplus::logLevel), logLevel)) &#123;     \</span></span><br><span class="line"><span class="meta">            LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf);         \</span></span><br><span class="line"><span class="meta">            log4cplus::tchar const * _logEvent                          \</span></span><br><span class="line"><span class="meta">                = _snpbuf.print (__VA_ARGS__);                          \</span></span><br><span class="line"><span class="meta">            log4cplus::detail::macro_forced_log (_l,                    \</span></span><br><span class="line"><span class="meta">                log4cplus::logLevel, _logEvent,                         \</span></span><br><span class="line"><span class="meta">                LOG4CPLUS_MACRO_FILE (), __LINE__,                      \</span></span><br><span class="line"><span class="meta">                LOG4CPLUS_MACRO_FUNCTION ());                           \</span></span><br><span class="line"><span class="meta">        &#125;                                                               \</span></span><br><span class="line"><span class="meta">    &#125; while(0)                                                          \</span></span><br><span class="line"><span class="meta">    LOG4CPLUS_RESTORE_DOWHILE_WARNING()</span></span><br></pre></td></tr></table></figure><p>LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#  <span class="keyword">define</span> LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var)     \</span></span><br><span class="line"><span class="meta">    log4cplus::helpers::snprintf_buf &amp; var                  \</span></span><br><span class="line"><span class="meta">        = log4cplus::detail::get_macro_body_snprintf_buf ()</span></span><br></pre></td></tr></table></figure><p>snprintf_buf::print</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">tchar <span class="type">const</span> *</span></span><br><span class="line"><span class="function"><span class="title">snprintf_buf::print</span> <span class="params">(tchar <span class="type">const</span> * fmt, ...)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">assert</span> (fmt);</span><br><span class="line"></span><br><span class="line">    tchar <span class="type">const</span> * str = <span class="literal">nullptr</span>;</span><br><span class="line">    <span class="type">int</span> ret = <span class="number">0</span>;</span><br><span class="line">    std::va_list args;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">do</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">va_start</span> (args, fmt);</span><br><span class="line">        ret = <span class="built_in">print_va_list</span> (str, fmt, args);</span><br><span class="line">        <span class="built_in">va_end</span> (args);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (ret == <span class="number">-1</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> str;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>snprintf_buf::print_va_list</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span></span></span><br><span class="line"><span class="function"><span class="title">snprintf_buf::print_va_list</span> <span class="params">(tchar <span class="type">const</span> * &amp; str, tchar <span class="type">const</span> * fmt,</span></span></span><br><span class="line"><span class="params"><span class="function">    std::va_list args)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> printed;</span><br><span class="line">    std::<span class="type">size_t</span> <span class="type">const</span> fmt_len = std::char_traits&lt;tchar&gt;::<span class="built_in">length</span> (fmt);</span><br><span class="line">    std::<span class="type">size_t</span> buf_size = buf.<span class="built_in">size</span> ();</span><br><span class="line">    std::<span class="type">size_t</span> <span class="type">const</span> output_estimate = fmt_len + fmt_len / <span class="number">2</span> + <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span> (output_estimate &gt; buf_size)</span><br><span class="line">        buf.<span class="built_in">resize</span> (buf_size = output_estimate);</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line"></span><br><span class="line">    printed = <span class="built_in">vsntprintf</span> (&amp;buf[<span class="number">0</span>], buf_size - <span class="number">1</span>, fmt, args);</span><br><span class="line">    <span class="keyword">if</span> (printed == <span class="number">-1</span>)</span><br><span class="line">    &#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined (EILSEQ)</span></span><br><span class="line">        <span class="keyword">if</span> (errno == EILSEQ)</span><br><span class="line">        &#123;</span><br><span class="line">            LogLog::<span class="built_in">getLogLog</span> ()-&gt;<span class="built_in">error</span> (</span><br><span class="line">                <span class="built_in">LOG4CPLUS_TEXT</span> (<span class="string">&quot;Character conversion error when printing&quot;</span>));</span><br><span class="line">            <span class="comment">// Return zero to terminate the outer loop in</span></span><br><span class="line">            <span class="comment">// snprintf_buf::print().</span></span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">        buf_size *= <span class="number">2</span>;</span><br><span class="line">        buf.<span class="built_in">resize</span> (buf_size);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (printed &gt;= <span class="built_in">static_cast</span>&lt;<span class="type">int</span>&gt;(buf_size - <span class="number">1</span>))</span><br><span class="line">    &#123;</span><br><span class="line">        buf_size = printed + <span class="number">2</span>;</span><br><span class="line">        buf.<span class="built_in">resize</span> (buf_size);</span><br><span class="line">        printed = <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        buf[printed] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    str = &amp;buf[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">return</span> printed;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其实就是使用了C语音的可变参数宏实现参数可变</p><ul><li>va_start</li><li>va_arg</li><li>va_end</li></ul><p>vadefs.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">elif</span> defined _M_IX86 &amp;&amp; !defined _M_HYBRID_X86_ARM64</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> _INTSIZEOF(n)          ((sizeof(n) + sizeof(int) - 1) &amp; ~(sizeof(int) - 1))</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> __crt_va_start_a(ap, v) ((void)(ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v)))</span></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> __crt_va_arg(ap, t)     (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))</span></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> __crt_va_end(ap)        ((void)(ap = (va_list)0))</span></span><br></pre></td></tr></table></figure><p>使用了 _vswprintf_p（sprintf） 做格式化</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> _vswprintf_p(</span><br><span class="line">   <span class="type">wchar_t</span> *buffer,</span><br><span class="line">   <span class="type">size_t</span> count,</span><br><span class="line">   <span class="type">const</span> <span class="type">wchar_t</span> *format,</span><br><span class="line">   va_list argptr</span><br><span class="line">);</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">sprintf</span> <span class="params">( </span></span></span><br><span class="line"><span class="params"><span class="function">    <span class="type">char</span> * str, </span></span></span><br><span class="line"><span class="params"><span class="function">    <span class="type">const</span> <span class="type">char</span> * format, </span></span></span><br><span class="line"><span class="params"><span class="function">    ... )</span></span>;</span><br></pre></td></tr></table></figure><p>C语言的函数是从右往左压入栈的，比如一下内存分布</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">print_args</span><span class="params">(<span class="type">int</span> count, ...)</span> &#123;</span><br><span class="line"><span class="type">int</span> i, value;</span><br><span class="line">va_list arg_ptr;</span><br><span class="line">va_start(arg_ptr, count);</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>; i&lt;count; i++) &#123;</span><br><span class="line">value = va_arg(arg_ptr,<span class="type">int</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;position %d = %d\n&quot;</span>, i+<span class="number">1</span>, value);</span><br><span class="line">&#125;</span><br><span class="line">va_end(arg_ptr);</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>* argv[])</span> &#123;</span><br><span class="line">print_args(<span class="number">5</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">| 5 |   // 高位地址</span><br><span class="line">| 4 |</span><br><span class="line">| 3 |</span><br><span class="line">| 2 |</span><br><span class="line">| 1 |   // arg_ptr</span><br><span class="line">| 5 |   // count</span><br></pre></td></tr></table></figure><h3 id="日志打印流程"><a href="#日志打印流程" class="headerlink" title="日志打印流程"></a>日志打印流程</h3><h4 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h4><ul><li>Logger::log</li><li>LoggerImpl::log：等级</li><li>LoggerImpl::forcedLog：获取 InternalLoggingEvent</li><li>LoggerImpl::callAppenders：遍历父子附加器</li><li>AppenderAttachableImpl::appendLoopOnAppenders：遍历附加器列表</li><li>Appender::doAppend：同步异步</li><li>Appender::syncDoAppend：检查阈值、过滤器、锁</li><li>FileAppenderBase::append：文件打开、锁定（进程同步）、格式化附加、刷新</li><li>SimpleLayout::formatAndAppend：附加</li></ul><h4 id="原理-1"><a href="#原理-1" class="headerlink" title="原理"></a>原理</h4><p>Logger::log</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">Logger::log</span> <span class="params">(LogLevel ll, <span class="type">const</span> log4cplus::tstring&amp; message, <span class="type">const</span> <span class="type">char</span>* file,</span></span></span><br><span class="line"><span class="params"><span class="function">    <span class="type">int</span> line, <span class="type">const</span> <span class="type">char</span>* function)</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    value-&gt;<span class="built_in">log</span> (ll, message, file, line, function ? function : <span class="string">&quot;&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>LoggerImpl::log：等级</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">LoggerImpl::log</span><span class="params">(LogLevel loglevel,</span></span></span><br><span class="line"><span class="params"><span class="function">                <span class="type">const</span> log4cplus::tstring&amp; message,</span></span></span><br><span class="line"><span class="params"><span class="function">                <span class="type">const</span> <span class="type">char</span>* file,</span></span></span><br><span class="line"><span class="params"><span class="function">                <span class="type">int</span> line,</span></span></span><br><span class="line"><span class="params"><span class="function">                <span class="type">const</span> <span class="type">char</span>* function)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">isEnabledFor</span>(loglevel)) &#123;</span><br><span class="line">        forcedLog(loglevel, message, file, line, function ? function : <span class="string">&quot;&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>LoggerImpl::forcedLog：获取 InternalLoggingEvent</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">LoggerImpl::forcedLog</span><span class="params">(LogLevel loglevel,</span></span></span><br><span class="line"><span class="params"><span class="function">                      <span class="type">const</span> log4cplus::tstring&amp; message,</span></span></span><br><span class="line"><span class="params"><span class="function">                      <span class="type">const</span> <span class="type">char</span>* file,</span></span></span><br><span class="line"><span class="params"><span class="function">                      <span class="type">int</span> line,</span></span></span><br><span class="line"><span class="params"><span class="function">                      <span class="type">const</span> <span class="type">char</span>* function)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    spi::InternalLoggingEvent &amp; ev = internal::<span class="built_in">get_ptd</span> ()-&gt;forced_log_ev;</span><br><span class="line">    <span class="built_in">assert</span> (function);</span><br><span class="line">    ev.<span class="built_in">setLoggingEvent</span> (<span class="keyword">this</span>-&gt;<span class="built_in">getName</span>(), loglevel, message, file, line,</span><br><span class="line">        function);</span><br><span class="line">    <span class="built_in">callAppenders</span>(ev);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>LoggerImpl::callAppenders：遍历父子附加器</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">LoggerImpl::callAppenders</span><span class="params">(<span class="type">const</span> InternalLoggingEvent&amp; event)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> writes = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> LoggerImpl* c = <span class="keyword">this</span>; c != <span class="literal">nullptr</span>; c=c-&gt;parent.<span class="built_in">get</span>()) &#123;</span><br><span class="line">        writes += c-&gt;<span class="built_in">appendLoopOnAppenders</span>(event);</span><br><span class="line">        <span class="keyword">if</span>(!c-&gt;additive) &#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// No appenders in hierarchy, warn user only once.</span></span><br><span class="line">    <span class="keyword">if</span>(!hierarchy.emittedNoAppenderWarning &amp;&amp; writes == <span class="number">0</span>) &#123;</span><br><span class="line">        helpers::<span class="built_in">getLogLog</span>().<span class="built_in">error</span>(</span><br><span class="line">            <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;No appenders could be found for logger (&quot;</span>)</span><br><span class="line">            + <span class="built_in">getName</span>()</span><br><span class="line">            + <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;).&quot;</span>));</span><br><span class="line">        helpers::<span class="built_in">getLogLog</span>().<span class="built_in">error</span>(</span><br><span class="line">            <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Please initialize the log4cplus system properly.&quot;</span>));</span><br><span class="line">        hierarchy.emittedNoAppenderWarning = <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>AppenderAttachableImpl::appendLoopOnAppenders：遍历附加器列表</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span></span></span><br><span class="line"><span class="function"><span class="title">AppenderAttachableImpl::appendLoopOnAppenders</span><span class="params">(<span class="type">const</span> spi::InternalLoggingEvent&amp; event)</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="function">thread::MutexGuard <span class="title">guard</span> <span class="params">(appender_list_mutex)</span></span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp; appender : appenderList)</span><br><span class="line">    &#123;</span><br><span class="line">        ++count;</span><br><span class="line">        appender-&gt;<span class="built_in">doAppend</span>(event);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Appender::doAppend：同步异步</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">Appender::doAppend</span><span class="params">(<span class="type">const</span> log4cplus::spi::InternalLoggingEvent&amp; event)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> ! defined (LOG4CPLUS_SINGLE_THREADED)</span></span><br><span class="line">    <span class="keyword">if</span> (async)</span><br><span class="line">    &#123;</span><br><span class="line">        event.<span class="built_in">gatherThreadSpecificData</span> ();</span><br><span class="line">        std::<span class="built_in">atomic_fetch_add_explicit</span> (&amp;in_flight, std::<span class="built_in">size_t</span> (<span class="number">1</span>),</span><br><span class="line">            std::memory_order_relaxed);</span><br><span class="line">        <span class="keyword">try</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">enqueueAsyncDoAppend</span> (<span class="built_in">SharedAppenderPtr</span> (<span class="keyword">this</span>), event);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">catch</span> (...)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">subtract_in_flight</span> ();</span><br><span class="line">            <span class="keyword">throw</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">        <span class="built_in">syncDoAppend</span> (event);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Appender::syncDoAppend：检查阈值、过滤器、锁</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">Appender::syncDoAppend</span><span class="params">(<span class="type">const</span> log4cplus::spi::InternalLoggingEvent&amp; event)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">thread::MutexGuard <span class="title">guard</span> <span class="params">(access_mutex)</span></span>;</span><br><span class="line">    <span class="keyword">if</span>(closed) &#123;</span><br><span class="line">        helpers::<span class="built_in">getLogLog</span>().<span class="built_in">error</span>(</span><br><span class="line">            <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Attempted to append to closed appender named [&quot;</span>)</span><br><span class="line">            + name</span><br><span class="line">            + <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;].&quot;</span>));</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// Check appender&#x27;s threshold logging level.</span></span><br><span class="line">    <span class="keyword">if</span> (! <span class="built_in">isAsSevereAsThreshold</span>(event.<span class="built_in">getLogLevel</span>()))</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    <span class="comment">// Evaluate filters attached to this appender.</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">checkFilter</span>(filter.<span class="built_in">get</span>(), event) == spi::DENY)</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    <span class="comment">// Lock system wide lock.</span></span><br><span class="line">    helpers::LockFileGuard lfguard;</span><br><span class="line">    <span class="keyword">if</span> (useLockFile &amp;&amp; lockFile.<span class="built_in">get</span> ())</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">try</span></span><br><span class="line">        &#123;</span><br><span class="line">            lfguard.<span class="built_in">attach_and_lock</span> (*lockFile);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">catch</span> (std::runtime_error <span class="type">const</span> &amp;)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// Finally append given event.</span></span><br><span class="line">    <span class="built_in">append</span>(event);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>FileAppenderBase::append：文件打开、锁定（进程同步）、格式化附加、刷新</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">FileAppenderBase::append</span><span class="params">(<span class="type">const</span> spi::InternalLoggingEvent&amp; event)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!out.<span class="built_in">good</span>()) &#123;</span><br><span class="line">        <span class="keyword">if</span>(!<span class="built_in">reopen</span>()) &#123;</span><br><span class="line">            <span class="built_in">getErrorHandler</span>()-&gt;<span class="built_in">error</span>(  <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;file is not open: &quot;</span>)</span><br><span class="line">                                     + filename);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// Resets the error handler to make it</span></span><br><span class="line">        <span class="comment">// ready to handle a future append error.</span></span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="built_in">getErrorHandler</span>()-&gt;<span class="built_in">reset</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (useLockFile)</span><br><span class="line">        out.<span class="built_in">seekp</span> (<span class="number">0</span>, std::ios_base::end);</span><br><span class="line"></span><br><span class="line">    layout-&gt;formatAndAppend(out, event);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(immediateFlush || useLockFile)</span><br><span class="line">        out.<span class="built_in">flush</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>SimpleLayout::formatAndAppend：附加</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span></span></span><br><span class="line"><span class="function"><span class="title">SimpleLayout::formatAndAppend</span><span class="params">(log4cplus::tostream&amp; output,</span></span></span><br><span class="line"><span class="params"><span class="function">                              <span class="type">const</span> log4cplus::spi::InternalLoggingEvent&amp; event)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    output &lt;&lt; llmCache.<span class="built_in">toString</span>(event.<span class="built_in">getLogLevel</span>())</span><br><span class="line">           &lt;&lt; <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot; - &quot;</span>)</span><br><span class="line">           &lt;&lt; event.<span class="built_in">getMessage</span>()</span><br><span class="line">           &lt;&lt; <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="源码编译"><a href="#源码编译" class="headerlink" title="源码编译"></a>源码编译</h2><h3 id="默认编译"><a href="#默认编译" class="headerlink" title="默认编译"></a>默认编译</h3><p>编译成动态库，带有很多例子项目</p><h3 id="去除例子（只编译库）"><a href="#去除例子（只编译库）" class="headerlink" title="去除例子（只编译库）"></a>去除例子（只编译库）</h3><h4 id="修改记录"><a href="#修改记录" class="headerlink" title="修改记录"></a>修改记录</h4><p><a href="https://github.com/huihut/log4cplus/commit/5d7e51ac6a43e1eaa623e5d2272651458edf85c6">https://github.com/huihut/log4cplus/commit/5d7e51ac6a43e1eaa623e5d2272651458edf85c6</a></p><h4 id="修改内容"><a href="#修改内容" class="headerlink" title="修改内容"></a>修改内容</h4><p>.&#x2F;CMakeLists.txt</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">option</span>(LOG4CPLUS_BUILD_TESTING <span class="string">&quot;Build the test suite.&quot;</span> <span class="keyword">OFF</span>)</span><br><span class="line"><span class="keyword">option</span>(LOG4CPLUS_BUILD_LOGGINGSERVER <span class="string">&quot;Build the logging server.&quot;</span> <span class="keyword">OFF</span>)</span><br><span class="line">...</span><br><span class="line"><span class="keyword">option</span>(WITH_UNIT_TESTS <span class="string">&quot;Enable unit tests&quot;</span> <span class="keyword">OFF</span>)</span><br></pre></td></tr></table></figure><h3 id="编译成静态库"><a href="#编译成静态库" class="headerlink" title="编译成静态库"></a>编译成静态库</h3><h4 id="修改记录-1"><a href="#修改记录-1" class="headerlink" title="修改记录"></a>修改记录</h4><p><a href="https://github.com/huihut/log4cplus/commit/4e02f06a5549afca1183801a1424eee221a36bb5">https://github.com/huihut/log4cplus/commit/4e02f06a5549afca1183801a1424eee221a36bb5</a></p><h4 id="修改内容-1"><a href="#修改内容-1" class="headerlink" title="修改内容"></a>修改内容</h4><p>.&#x2F;src&#x2F;CMakeLists.txt</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">add_compile_definitions</span> (LOG4CPLUS_STATIC)</span><br><span class="line">...</span><br><span class="line"><span class="keyword">add_library</span> (<span class="variable">$&#123;log4cplus&#125;</span> STATIC <span class="variable">$&#123;log4cplus_sources&#125;</span>)</span><br></pre></td></tr></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="将日志输出到控制台"><a href="#将日志输出到控制台" class="headerlink" title="将日志输出到控制台"></a>将日志输出到控制台</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;log4cplus/log4cplus.h&gt;</span></span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//用Initializer类进行初始化</span></span><br><span class="line">    log4cplus::Initializer initializer;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第1步：创建ConsoleAppender</span></span><br><span class="line">    <span class="function">log4cplus::SharedAppenderPtr <span class="title">appender</span><span class="params">(<span class="keyword">new</span> log4cplus::ConsoleAppender())</span></span>;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第2步：设置Appender的名称和输出格式（SimpleLayout）</span></span><br><span class="line">    appender-&gt;<span class="built_in">setName</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;console&quot;</span>));</span><br><span class="line">    appender-&gt;<span class="built_in">setLayout</span>(std::<span class="built_in">unique_ptr</span>&lt;log4cplus::Layout&gt;(<span class="keyword">new</span> log4cplus::SimpleLayout));</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第3步：获得一个Logger实例，并设置其日志输出等级阈值</span></span><br><span class="line">    log4cplus::Logger logger = log4cplus::Logger::<span class="built_in">getInstance</span>(<span class="built_in">LOG4CPLUS_TEXT</span> (<span class="string">&quot;test&quot;</span>));</span><br><span class="line">    logger.<span class="built_in">setLogLevel</span>(log4cplus::INFO_LOG_LEVEL);</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第4步：为Logger实例添加ConsoleAppender</span></span><br><span class="line">    logger.<span class="built_in">addAppender</span>(appender);</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第5步：使用宏将日志输出</span></span><br><span class="line">    <span class="built_in">LOG4CPLUS_INFO</span>(logger, <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Hello world&quot;</span>));</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="将日志输出到控制台并写入文件"><a href="#将日志输出到控制台并写入文件" class="headerlink" title="将日志输出到控制台并写入文件"></a>将日志输出到控制台并写入文件</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;log4cplus/log4cplus.h&gt;</span></span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//用Initializer类进行初始化</span></span><br><span class="line">    log4cplus::Initializer initializer;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第1步：创建ConsoleAppender和FileAppender(参数app表示内容追加到文件)</span></span><br><span class="line">    <span class="function">log4cplus::SharedAppenderPtr <span class="title">consoleAppender</span><span class="params">(<span class="keyword">new</span> log4cplus::ConsoleAppender)</span></span>;</span><br><span class="line">    <span class="function">log4cplus::SharedAppenderPtr <span class="title">fileAppender</span><span class="params">(<span class="keyword">new</span> log4cplus::FileAppender(</span></span></span><br><span class="line"><span class="params"><span class="function">                                                  LOG4CPLUS_TEXT(<span class="string">&quot;log.txt&quot;</span>),</span></span></span><br><span class="line"><span class="params"><span class="function">                                                  std::ios_base::app))</span></span>;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第2步：设置Appender的名称和输出格式</span></span><br><span class="line">    <span class="comment">//ConsoleAppender使用SimpleLayout</span></span><br><span class="line">    <span class="comment">//FileAppender使用PatternLayout</span></span><br><span class="line">    consoleAppender-&gt;<span class="built_in">setName</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;console&quot;</span>));</span><br><span class="line">    consoleAppender-&gt;<span class="built_in">setLayout</span>(std::<span class="built_in">unique_ptr</span>&lt;log4cplus::Layout&gt;(<span class="keyword">new</span> log4cplus::<span class="built_in">SimpleLayout</span>()));</span><br><span class="line">    </span><br><span class="line">    fileAppender-&gt;<span class="built_in">setName</span>(<span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;file&quot;</span>));</span><br><span class="line">    log4cplus::tstring pattern = <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;%D&#123;%m/%d/%y %H:%M:%S,%Q&#125; [%t] %-5p %c - %m [%l]%n&quot;</span>);</span><br><span class="line">    fileAppender-&gt;<span class="built_in">setLayout</span>(std::<span class="built_in">unique_ptr</span>&lt;log4cplus::Layout&gt;(<span class="keyword">new</span> log4cplus::<span class="built_in">PatternLayout</span>(pattern)));</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第3步：获得一个Logger实例，并设置其日志输出等级阈值</span></span><br><span class="line">    log4cplus::Logger logger = log4cplus::Logger::<span class="built_in">getInstance</span>(<span class="built_in">LOG4CPLUS_TEXT</span> (<span class="string">&quot;test&quot;</span>));</span><br><span class="line">    logger.<span class="built_in">setLogLevel</span>(log4cplus::INFO_LOG_LEVEL);</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第4步：为Logger实例添加ConsoleAppender和FileAppender</span></span><br><span class="line">    logger.<span class="built_in">addAppender</span>(consoleAppender);</span><br><span class="line">    logger.<span class="built_in">addAppender</span>(fileAppender);</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//第5步：使用宏将日志输出</span></span><br><span class="line">    <span class="built_in">LOG4CPLUS_INFO</span>(logger, <span class="built_in">LOG4CPLUS_TEXT</span>(<span class="string">&quot;Hello world&quot;</span>));</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="log4cplusplus"><a href="#log4cplusplus" class="headerlink" title="log4cplusplus"></a>log4cplusplus</h1><p><a href="https://github.com/huihut/log4cplusplus">https://github.com/huihut/log4cplusplus</a></p><h2 id="简介-1"><a href="#简介-1" class="headerlink" title="简介"></a>简介</h2><p>log4cplusplus 是 log4cplus 的包装库</p><ul><li>线程安全</li><li>支持异步</li><li>支持中文路径和内容</li><li>支持输出到文件、控制台、调试器</li><li>支持格式化打印</li></ul><h2 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">enum</span> <span class="title class_">Log4CPlusPlusLevel</span></span><br><span class="line">&#123;</span><br><span class="line">LogDebugLevel = <span class="number">10000</span>,</span><br><span class="line">LogInfoLevel = <span class="number">20000</span>,</span><br><span class="line">LogWarnLevel = <span class="number">30000</span>,</span><br><span class="line">LogErrorLevel = <span class="number">40000</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Log4CPlusPlus</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="built_in">Log4CPlusPlus</span>() &#123;&#125;</span><br><span class="line"><span class="keyword">virtual</span> ~<span class="built_in">Log4CPlusPlus</span>() &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">Release</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">AddFileAppender</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">const</span> <span class="type">wchar_t</span> *file_path = DEFALT_LOG_FILE_PATH,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">const</span> <span class="type">wchar_t</span> *file_name = DEFALT_LOG_FILE_NAME,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">unsigned</span> <span class="type">long</span> max_file_size = DEFALT_MAX_FILE_SIZE,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">unsigned</span> <span class="type">long</span> max_file_count = DEFALT_MAX_FILE_COUNT,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">bool</span> is_async = DEFALT_IS_ASYNC</span></span></span><br><span class="line"><span class="params"><span class="function">)</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">EnableDebuggerAppender</span><span class="params">(<span class="type">bool</span> enable)</span> </span>= <span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">EnableConsoleAppender</span><span class="params">(<span class="type">bool</span> enable)</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">const</span> <span class="type">wchar_t</span> * <span class="title">GetLogPath</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">WriteLog</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">Log4CPlusPlusLevel logLevel,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">const</span> <span class="type">char</span>* file,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">int</span> line,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">const</span> <span class="type">char</span>* function,</span></span></span><br><span class="line"><span class="params"><span class="function"><span class="type">const</span> <span class="type">wchar_t</span> *format, ...)</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h2 id="使用-1"><a href="#使用-1" class="headerlink" title="使用"></a>使用</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;log4cplusplus.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">log4cplus::Log4CPlusPlus* log = <span class="built_in">CreateLog4CPlusPlus</span>();</span><br><span class="line"><span class="keyword">if</span> (log)</span><br><span class="line">&#123;</span><br><span class="line">log-&gt;<span class="built_in">AddFileAppender</span>();</span><br><span class="line">log-&gt;<span class="built_in">EnableDebuggerAppender</span>(<span class="literal">true</span>);</span><br><span class="line">log-&gt;<span class="built_in">EnableConsoleAppender</span>(<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">LOG4CPLUSPLUS_DEBUG</span>(log, <span class="string">L&quot;log test&quot;</span>);</span><br><span class="line"><span class="built_in">LOG4CPLUSPLUS_INFO</span>(log, <span class="string">L&quot;log test %s&quot;</span>, <span class="string">L&quot;info&quot;</span>);</span><br><span class="line"><span class="built_in">LOG4CPLUSPLUS_WARN</span>(log, <span class="string">L&quot;log test %s %d&quot;</span>, <span class="string">L&quot;warn&quot;</span>, <span class="number">123</span>);</span><br><span class="line"><span class="built_in">LOG4CPLUSPLUS_ERROR</span>(log, <span class="string">L&quot;log test %f&quot;</span>, <span class="number">3.14</span>);</span><br><span class="line"><span class="built_in">LOG4CPLUSPLUS_ERROR</span>(log, <span class="string">L&quot;中文日志测试!!&quot;</span>);</span><br><span class="line"></span><br><span class="line">log-&gt;<span class="built_in">Release</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;p&gt;Log4cplus 是 log4j 的 C++ 实现，其接口和使用逻辑与 log4j 基本保持一致。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;log4cplus 具有线程安全、灵活、以及多粒度控制的特点&lt;/li&gt;
&lt;li&gt;可以通过将日志划分优先级使其可以面向程序调试、运行、测试、和维护等全生命周期&lt;/li&gt;
&lt;li&gt;可以选择将日志输出到控制台、调试器、文件、服务器&lt;/li&gt;
&lt;li&gt;可以通过指定策略对日志进行定期备份&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>Windows编译构建CEF发行版</title>
    <link href="https://blog.huihut.com/2020/03/07/WindowsBuildCEF/"/>
    <id>https://blog.huihut.com/2020/03/07/WindowsBuildCEF/</id>
    <published>2020-03-06T16:46:00.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<h2 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h2><p>在 CEF 发行版网站（<a href="http://opensource.spotify.com/cefbuilds/index.html">Chromium Embedded Framework (CEF) Automated Builds</a>）下载对应的 Standard Distribution 版本，本文以 CEF 75.1.14（<a href="http://opensource.spotify.com/cefbuilds/cef_binary_75.1.8%2Bg84fed5d%2Bchromium-75.0.3770.100_windows32.tar.bz2">cef_binary_75.1.8+g84fed5d+chromium-75.0.3770.100_windows32.tar.bz2</a>）为例</p><span id="more"></span><h2 id="使用-CMake-构建"><a href="#使用-CMake-构建" class="headerlink" title="使用 CMake 构建"></a>使用 CMake 构建</h2><p>打开 cmake-gui，设置源码和生成路径：</p><ul><li>Where is the source code: <code>D:/code/git/cef-builds/cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32</code></li><li>Where to build the binaries: <code>D:/code/git/cef-builds/cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32/build</code></li></ul><p>点击 Configure 生成配置，修改：</p><ul><li>生成动态库（个人偏好）：<code>CEF_RUNTIME_LIBRARY_FLAG</code> 从 <code>/MT</code> 改为 <code>/MD</code></li><li>不用沙盒（原因见 <a href="https://bitbucket.org/chromiumembedded/cef/wiki/Tutorial#markdown-header-windows-build-steps">这里</a>）：不勾选 <code>USE_SANDBOX</code></li></ul><p>点击 Configure、Generate 生成 VS 工程</p><h2 id="使用-VS-编译"><a href="#使用-VS-编译" class="headerlink" title="使用 VS 编译"></a>使用 VS 编译</h2><p>ceftests 项目会有文件格式错误</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">1&gt;------ 已启动生成: 项目: ceftests, 配置: Debug Win32 ------</span><br><span class="line">1&gt;os_rendering_unittest.cc</span><br><span class="line">1&gt;D:\code\git\cef-builds\cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32\tests\ceftests\os_rendering_unittest.cc(794): error C2220: 警告被视为错误 - 没有生成“object”文件</span><br><span class="line">1&gt;D:\code\git\cef-builds\cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32\tests\ceftests\os_rendering_unittest.cc(794): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失</span><br><span class="line">1&gt;D:\code\git\cef-builds\cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32\tests\ceftests\os_rendering_unittest.cc(955): error C2001: 常量中有换行符</span><br><span class="line">1&gt;D:\code\git\cef-builds\CEF 79.1.38\cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32\tests\ceftests\os_rendering_unittest.cc(998): error C2001: 常量中有换行符</span><br><span class="line">1&gt;D:\code\git\cef-builds\cef_binary_75.1.14+gc81164e+chromium-75.0.3770.100_windows32\tests\ceftests\os_rendering_unittest.cc(998): fatal error C1075: “&#123;”: 未找到匹配令牌</span><br><span class="line">1&gt;已完成生成项目“ceftests.vcxproj”的操作 - 失败。</span><br></pre></td></tr></table></figure><p>用记事本打开 <code>os_rendering_unittest.cc</code> 文件，另存为 <code>带有 BOM 的 UTF-8</code> 编码，覆盖原文件。</p><p>重新编译则会编译通过。</p><p>然后设置 <code>cefclient</code> 为启动项目，F5，则可看到 Google 为主页的一个浏览器 Demo</p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;下载&quot;&gt;&lt;a href=&quot;#下载&quot; class=&quot;headerlink&quot; title=&quot;下载&quot;&gt;&lt;/a&gt;下载&lt;/h2&gt;&lt;p&gt;在 CEF 发行版网站（&lt;a href=&quot;http://opensource.spotify.com/cefbuilds/index.html&quot;&gt;Chromium Embedded Framework (CEF) Automated Builds&lt;/a&gt;）下载对应的 Standard Distribution 版本，本文以 CEF 75.1.14（&lt;a href=&quot;http://opensource.spotify.com/cefbuilds/cef_binary_75.1.8%2Bg84fed5d%2Bchromium-75.0.3770.100_windows32.tar.bz2&quot;&gt;cef_binary_75.1.8+g84fed5d+chromium-75.0.3770.100_windows32.tar.bz2&lt;/a&gt;）为例&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="CEF" scheme="https://blog.huihut.com/tags/CEF/"/>
    
  </entry>
  
  <entry>
    <title>一个基于 C# 的简单的线程安全日志模块</title>
    <link href="https://blog.huihut.com/2019/07/28/LogConsumer/"/>
    <id>https://blog.huihut.com/2019/07/28/LogConsumer/</id>
    <published>2019-07-28T06:14:40.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<p>一个基于 C# 的简单的线程安全日志模块，它使用生产者 - 消费者模式，可以在 .NET Framework 和 .Net Core 中使用。</p><p>Github 地址：<a href="https://github.com/huihut/LogConsumer">LogConsumer</a></p><span id="more"></span><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ol><li>将 <a href="https://github.com/huihut/LogConsumer/blob/master/LogConsumer/LogConsumer.cs">LogConsumer.cs</a> 添加到你的项目中</li><li>将 <code>LogConsumer.cs</code> 中的 <code>logFileName</code> 修改为你的路径文件名</li><li>在需要输出日志的地方使用它 <figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HuiHut.LogConsumer.LogConsumer.Instance.Write(<span class="string">&quot;your log content&quot;</span>);</span><br></pre></td></tr></table></figure></li></ol><h2 id="编译运行"><a href="#编译运行" class="headerlink" title="编译运行"></a>编译运行</h2><ul><li>命令行  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">dotnet build</span><br><span class="line">dotnet .\LogConsumer\bin\Debug\netcoreapp2.1\LogConsumer.dll</span><br></pre></td></tr></table></figure></li><li>Visual Studio  <ol><li>打开 <code>LogConsumer.sln</code></li><li>生成解决方案，运行测试</li></ol></li></ul><h2 id="测试的日志文件示例"><a href="#测试的日志文件示例" class="headerlink" title="测试的日志文件示例"></a>测试的日志文件示例</h2><p>10 个线程，每个线程抛出  10 条日志的测试</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line">Data       Time      Namespace          Class           Method    LogContent</span><br><span class="line">----------------------------------------------------------------------------------</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 0</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 1</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 2</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 3</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 4</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 5</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 6</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 7</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 5 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 8</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 2 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 3 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 6 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 7 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] index = 9</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 0 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 1 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 9 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 8 ] Thread is finished.</span><br><span class="line">2019-05-10 01:50:09  HuiHut.LogConsumer:LogConsumerTest.WriteLog  [ 4 ] Thread is finished.</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;一个基于 C# 的简单的线程安全日志模块，它使用生产者 - 消费者模式，可以在 .NET Framework 和 .Net Core 中使用。&lt;/p&gt;
&lt;p&gt;Github 地址：&lt;a href=&quot;https://github.com/huihut/LogConsumer&quot;&gt;LogConsumer&lt;/a&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Dotnet" scheme="https://blog.huihut.com/tags/Dotnet/"/>
    
    <category term="C#" scheme="https://blog.huihut.com/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>获取 Windows 操作系统的系统、网络、硬件、软件等信息</title>
    <link href="https://blog.huihut.com/2019/07/28/GetWindowsInfo/"/>
    <id>https://blog.huihut.com/2019/07/28/GetWindowsInfo/</id>
    <published>2019-07-28T05:00:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Github"><a href="#Github" class="headerlink" title="Github"></a>Github</h2><ul><li>源码：<a href="https://github.com/huihut/WindowsInfo.Net/">WindowsInfo.Net</a></li><li>可执行文件：<a href="https://github.com/huihut/WindowsInfo.Net/releases">WindowsInfo.Net.exe</a></li></ul><span id="more"></span><h2 id="获取的信息"><a href="#获取的信息" class="headerlink" title="获取的信息"></a>获取的信息</h2><p>能获得的信息如下（系统、硬件、网络信息已打码）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">---------  系统信息  ---------</span><br><span class="line">计算机名：***</span><br><span class="line">登录用户名：***</span><br><span class="line">操作系统类型：***</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">---------  硬件信息  ---------</span><br><span class="line">本机的MAC地址：***</span><br><span class="line">主板序列号：***</span><br><span class="line">主板制造厂商：***</span><br><span class="line">主板编号：***</span><br><span class="line">主板编号：***</span><br><span class="line">主板型号：***</span><br><span class="line">CPU序列号：***</span><br><span class="line">CPU编号：***</span><br><span class="line">CPU版本信息：***</span><br><span class="line">CPU名称信息：***</span><br><span class="line">CPU制造厂商：***</span><br><span class="line">物理硬盘序列号：***</span><br><span class="line">磁盘序列号：***</span><br><span class="line">网卡地址：***</span><br><span class="line">网卡硬件地址：***</span><br><span class="line">物理内存：***</span><br><span class="line">显卡PNPDeviceID：***</span><br><span class="line">声卡PNPDeviceID：***</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">---------  网络信息  ---------</span><br><span class="line">IP地址：***</span><br><span class="line">本地ip地址：***</span><br><span class="line">本地ip地址：***</span><br><span class="line">外网ip地址：***</span><br><span class="line">外网ip地址：***</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">---------  软件信息  ---------</span><br><span class="line">GitHub Desktop2.1.0</span><br><span class="line">Mozilla Firefox 68.0 (x86 en-US)68.0</span><br><span class="line">Microsoft OneDrive19.103.0527.0003</span><br><span class="line">Python 3.7.2 (32-bit)3.7.2150.0</span><br><span class="line">Microsoft Visual Studio Code (User)1.36.1</span><br><span class="line">***</span><br></pre></td></tr></table></figure><h2 id="硬件网络信息"><a href="#硬件网络信息" class="headerlink" title="硬件网络信息"></a>硬件网络信息</h2><p>硬件网络信息是通过 System.Management 里面的类方法获取的，具体类方法可查看官方文档：</p><p><a href="https://docs.microsoft.com/zh-cn/dotnet/api/system.management">System.Management Namespace</a></p><h2 id="软件信息"><a href="#软件信息" class="headerlink" title="软件信息"></a>软件信息</h2><p>软件信息是通过读取注册表的方式获取的，所以软件开发使用的话需要验证一下某些安全管家是否会警告。</p><ul><li>都有的信息：名字（DisplayName）</li><li>大部分都有的信息：名字（DisplayName）、版本号（DisplayVersion）、发行商（Publisher）、安装日期（InstallDate）</li><li>比较多信息的如下图：<br>  <img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/%E6%B3%A8%E5%86%8C%E8%A1%A8-VMware.png"></li></ul><h3 id="软件信息在注册表的路径"><a href="#软件信息在注册表的路径" class="headerlink" title="软件信息在注册表的路径"></a>软件信息在注册表的路径</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall\</span><br><span class="line">计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\</span><br></pre></td></tr></table></figure><h3 id="监控读取注册表"><a href="#监控读取注册表" class="headerlink" title="监控读取注册表"></a>监控读取注册表</h3><p>测试了一下读取注册表，360，腾讯管家不会警告，但有些软件（如：<a href="https://docs.microsoft.com/zh-cn/sysinternals/downloads/procmon">procmon</a>）能监控进程的读取的行为。</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/20190328110726.png"></p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;Github&quot;&gt;&lt;a href=&quot;#Github&quot; class=&quot;headerlink&quot; title=&quot;Github&quot;&gt;&lt;/a&gt;Github&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;源码：&lt;a href=&quot;https://github.com/huihut/WindowsInfo.Net/&quot;&gt;WindowsInfo.Net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;可执行文件：&lt;a href=&quot;https://github.com/huihut/WindowsInfo.Net/releases&quot;&gt;WindowsInfo.Net.exe&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Dotnet" scheme="https://blog.huihut.com/tags/Dotnet/"/>
    
    <category term="C#" scheme="https://blog.huihut.com/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>Unity3D 编辑器调试无响应问题</title>
    <link href="https://blog.huihut.com/2019/05/17/Unity3DEditorDebuggingNoResponse/"/>
    <id>https://blog.huihut.com/2019/05/17/Unity3DEditorDebuggingNoResponse/</id>
    <published>2019-05-17T07:14:00.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>使用 VS 在 Unity 编辑器中调试代码，点击 VS 的 <code>附加到 Unity</code>，Unity 编辑器按下 <code>Play</code> 之后，就会一直等待并且无其他响应，只能结束 Unity 进程。</p><span id="more"></span><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/%E4%BB%BB%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8%E4%B8%ADUnity%E6%97%A0%E5%93%8D%E5%BA%94.png" alt="任务管理器中 Unity 无响应"></p><h2 id="原因分析"><a href="#原因分析" class="headerlink" title="原因分析"></a>原因分析</h2><p>经过分析与测试，发现去掉代码中一个单例类的析构方法中的断点即可调试了，具体原因未知。</p><p>再测试了一下，在那个单例类的构造、析构方法中分别打断点，如下表：</p><table><thead><tr><th>测试</th><th>构造</th><th>析构</th><th>结果</th></tr></thead><tbody><tr><td>1</td><td></td><td></td><td>可调试</td></tr><tr><td>2</td><td>*</td><td></td><td>可调试</td></tr><tr><td>3</td><td></td><td>*</td><td>无响应</td></tr><tr><td>4</td><td>*</td><td>*</td><td>无响应</td></tr></tbody></table><blockquote><p>表中 <code>*</code> 代表打断点 </p></blockquote><p>可发现只要在那个单例类的析构中打断点就会造成 Unity 无响应。</p><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><p>删除析构方法中的断点，或者所有断点，再调试。</p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;问题描述&quot;&gt;&lt;a href=&quot;#问题描述&quot; class=&quot;headerlink&quot; title=&quot;问题描述&quot;&gt;&lt;/a&gt;问题描述&lt;/h2&gt;&lt;p&gt;使用 VS 在 Unity 编辑器中调试代码，点击 VS 的 &lt;code&gt;附加到 Unity&lt;/code&gt;，Unity 编辑器按下 &lt;code&gt;Play&lt;/code&gt; 之后，就会一直等待并且无其他响应，只能结束 Unity 进程。&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Unity" scheme="https://blog.huihut.com/tags/Unity/"/>
    
  </entry>
  
  <entry>
    <title>Python DeprecationWarning the imp module is deprecated in favour of importlib</title>
    <link href="https://blog.huihut.com/2019/01/21/PythonDeprecationWarningTheImpModuleIsDeprecatedInFavourOfImportlib/"/>
    <id>https://blog.huihut.com/2019/01/21/PythonDeprecationWarningTheImpModuleIsDeprecatedInFavourOfImportlib/</id>
    <published>2019-01-20T18:21:18.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="报错"><a href="#报错" class="headerlink" title="报错"></a>报错</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">E:\PyCharm 2018.2.5\helpers\pycharm\docrunner.py:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module&#x27;s documentation for alternative uses</span><br><span class="line">  import imp</span><br></pre></td></tr></table></figure><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>imp 从 Python 3.4 之后弃用了，建议使用 importlib 代替</p><span id="more"></span><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>打开 <code>E:\PyCharm 2018.2.5\helpers\pycharm\docrunner.py</code> 文件，做如下两步修改：</p><ol><li><p>在第一行，注释掉 <code>imp</code>，导入 <code>importlib</code></p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#import imp</span></span><br><span class="line"><span class="keyword">import</span> importlib</span><br></pre></td></tr></table></figure></li><li><p>在第 230 行的 <code>loadSource</code> 函数中，注释 <code>imp.load_source</code>，使用 <code>importlib.machinery.SourceFileLoader</code> 加载模块</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#module = imp.load_source(moduleName, fileName)</span></span><br><span class="line">module = importlib.machinery.SourceFileLoader(moduleName, fileName).load_module()</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;报错&quot;&gt;&lt;a href=&quot;#报错&quot; class=&quot;headerlink&quot; title=&quot;报错&quot;&gt;&lt;/a&gt;报错&lt;/h2&gt;&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;E:&#92;PyCharm 2018.2.5&#92;helpers&#92;pycharm&#92;docrunner.py:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module&amp;#x27;s documentation for alternative uses&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  import imp&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;h2 id=&quot;原因&quot;&gt;&lt;a href=&quot;#原因&quot; class=&quot;headerlink&quot; title=&quot;原因&quot;&gt;&lt;/a&gt;原因&lt;/h2&gt;&lt;p&gt;imp 从 Python 3.4 之后弃用了，建议使用 importlib 代替&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Python" scheme="https://blog.huihut.com/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>Windows 下源码编译 eos 人脸模型拟合库过程遇到的坑坑坑</title>
    <link href="https://blog.huihut.com/2019/01/13/CompileEOSOnWindows/"/>
    <id>https://blog.huihut.com/2019/01/13/CompileEOSOnWindows/</id>
    <published>2019-01-12T18:09:21.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://github.com/patrikhuber/eos">eos</a> 是一个用现代 C++11&#x2F;14 编写的轻量级三维形变人脸模型拟合库，下面介绍下编译它的步骤和遇到的一些坑坑坑坑！</p><ul><li>博文的前半部分是用手动安装的 opencv 和 boost 构建和编译的，一路是坑，最终没有编译成功；</li><li>博文的后半部分是用 <a href="https://github.com/Microsoft/vcpkg/">vcpkg</a> 构建系统安装的 opencv 和 boost 然后构建和编译的，最终编译成功，但是运行失败。</li></ul><p>至今为止，关于运行失败的 <a href="https://github.com/patrikhuber/eos/issues/245">issue</a> 作者也没有回复，希望有朝一日能填坑吧~</p><span id="more"></span><h2 id="初期编译环境"><a href="#初期编译环境" class="headerlink" title="初期编译环境"></a>初期编译环境</h2><ul><li>Windows 10</li><li>Visual Studio 2017</li><li>CMake 3.12.4</li><li>OpenCV 4.0.1</li><li>Boost 1.66.0</li></ul><h2 id="克隆配置"><a href="#克隆配置" class="headerlink" title="克隆配置"></a>克隆配置</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git clone --recursive git@github.com:patrikhuber/eos.git</span><br><span class="line">mkdir eos_build</span><br></pre></td></tr></table></figure><p>打开 CMake-gui，设置</p><ul><li>Where is the source code: <code>D:/code/VS/BabyCreator/eos</code></li><li>Where to build the binaries: <code>D:/code/VS/BabyCreator/eos_build</code></li></ul><p>点击 Configure，设置编译器</p><ul><li>Specify the generator for this project: Visual Studio 15 2017</li><li>Finish</li></ul><p>配置过程遇到如下错误。</p><h2 id="Found-OpenCV-Windows-Pack-but-it-has-no-binaries-compatible-with-your-configuration-错误"><a href="#Found-OpenCV-Windows-Pack-but-it-has-no-binaries-compatible-with-your-configuration-错误" class="headerlink" title="Found OpenCV Windows Pack but it has no binaries compatible with your configuration. 错误"></a>Found OpenCV Windows Pack but it has no binaries compatible with your configuration. 错误</h2><h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Found OpenCV Windows Pack but it has no binaries compatible with your</span><br><span class="line">configuration.</span><br><span class="line"></span><br><span class="line">You should manually point CMake variable OpenCV_DIR to your build of OpenCV</span><br><span class="line">library.</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/20181229012607.png" alt="20181229012607"></p><h3 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h3><p>能找到 OpenCV 路径，但找不到兼容的二进制文件。</p><p>出错的这个 OpenCV 是在 <a href="https://opencv.org/releases.html">opencv.org&#x2F;releases</a> 下载的 Win pack。</p><p>尝试过网友的解决方案【尝试二、三、四】都不能解决，最终通过【尝试五】重新下载源码编译解决，因此可能是构建环境或者编译器的问题。</p><h3 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h3><p>【尝试一】重新设置环境变量：<code>E:\opencv-4.0.1\opencv-4.0.1-winpack\opencv\build\x64\vc15\bin</code></p><p>【尝试二】在 <code>eos/CMakeCache.txt</code> 设置 OpenCV_DIR，不行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">set(OpenCV_DIR &quot;D:\\code\\VS\\BabyCreator\\eos\\3rdparty\\opencv\\build&quot;)</span><br><span class="line">find_package(OpenCV REQUIRED)</span><br></pre></td></tr></table></figure><p>【尝试三】在终端设置 OpenCV_DIR，不行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PS D:\code\VS\BabyCreator\eos&gt; cmake . -DOpenCV_DIR=D:\\code\\VS\\BabyCreator\\eos\\3rdparty\\opencv\\build\\OpenCVConfig.cmake</span><br></pre></td></tr></table></figure><p>【尝试四】在 find_package 前设置 OpenCV_FOUND 为 1，不行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">set(OpenCV_FOUND 1)</span><br><span class="line">find_package(OpenCV REQUIRED)</span><br></pre></td></tr></table></figure><p>【尝试五】下载源码编译 VS 2017 工程的 opencv，解决。</p><ol><li>在 CMake Configure、Generate</li><li>在 VS ALL_BUILD、INSTALL</li><li>执行 <code>install/setup_vars_opencv4.cmd</code></li><li>设置环境变量：<code>E:/opencv-4.0.1/opencv-4.0.1-vs-build/install/x86/vc15/bin</code></li></ol><h2 id="Imported-targets-and-dependency-information-not-available-for-Boost-version-错误"><a href="#Imported-targets-and-dependency-information-not-available-for-Boost-version-错误" class="headerlink" title="Imported targets and dependency information not available for Boost version 错误"></a>Imported targets and dependency information not available for Boost version 错误</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">CMake Warning at E:/CMake/share/cmake-3.12/Modules/FindBoost.cmake:577 (message):</span><br><span class="line">  Imported targets and dependency information not available for Boost version</span><br><span class="line">  (all versions older than 1.33)</span><br><span class="line">Call Stack (most recent call first):</span><br><span class="line">  E:/CMake/share/cmake-3.12/Modules/FindBoost.cmake:963 (_Boost_COMPONENT_DEPENDENCIES)</span><br><span class="line">  E:/CMake/share/cmake-3.12/Modules/FindBoost.cmake:1622 (_Boost_MISSING_DEPENDENCIES)</span><br><span class="line">  examples/CMakeLists.txt:22 (find_package)</span><br><span class="line">......</span><br><span class="line">Boost found at Boost_INCLUDE_DIR-NOTFOUND</span><br><span class="line">CMake Error: The following variables are used in this project, but they are set to NOTFOUND.</span><br><span class="line">Please set them or make sure they are set and tested correctly in the CMake files:</span><br><span class="line">D:/code/VS/BabyCreator/eos/examples/Boost_INCLUDE_DIR</span><br><span class="line">   used as include directory in directory D:/code/VS/BabyCreator/eos/examples</span><br><span class="line">   used as include directory in directory D:/code/VS/BabyCreator/eos/examples</span><br><span class="line">   used as include directory in directory D:/code/VS/BabyCreator/eos/examples</span><br><span class="line">   used as include directory in directory D:/code/VS/BabyCreator/eos/examples</span><br><span class="line"></span><br><span class="line">Configuring incomplete, errors occurred!</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/2018-12-29_015957.png" alt="2018-12-29_015957"></p><h3 id="原因-1"><a href="#原因-1" class="headerlink" title="原因"></a>原因</h3><p>没找到 Boost 库，原因是没配置好。</p><h3 id="解决-1"><a href="#解决-1" class="headerlink" title="解决"></a>解决</h3><p>尝试了如下方式后，这个问题变成了 <code>Unable to find the requested Boost libraries.</code></p><ol><li>下载 <a href="https://www.boost.org/users/download/">boost</a> </li><li>运行 <code>boost_1_66_0/b2.exe</code> 生成静态库</li><li>在 <code>eos/CMakeCache.txt</code> 配置 <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">set(BOOST_ROOT &quot;E:\\boost_1_66_0&quot;)</span><br><span class="line">set(BOOST_LIBRARYDIR $&#123;BOOST_ROOT&#125;/stage/lib)</span><br></pre></td></tr></table></figure></li></ol><h2 id="Unable-to-find-the-requested-Boost-libraries-错误"><a href="#Unable-to-find-the-requested-Boost-libraries-错误" class="headerlink" title="Unable to find the requested Boost libraries. 错误"></a>Unable to find the requested Boost libraries. 错误</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">CMake Error at E:/CMake/share/cmake-3.12/Modules/FindBoost.cmake:2048 (message):</span><br><span class="line">  Unable to find the requested Boost libraries.</span><br><span class="line"></span><br><span class="line">  Boost version: 1.66.0</span><br><span class="line"></span><br><span class="line">  Boost include path: E:/boost_1_66_0</span><br><span class="line"></span><br><span class="line">  Could not find the following Boost libraries:</span><br><span class="line"></span><br><span class="line">          boost_system</span><br><span class="line">          boost_filesystem</span><br><span class="line">          boost_program_options</span><br><span class="line"></span><br><span class="line">  No Boost libraries were found.  You may need to set BOOST_LIBRARYDIR to the</span><br><span class="line">  directory containing Boost libraries or BOOST_ROOT to the location of</span><br><span class="line">  Boost.</span><br><span class="line">Call Stack (most recent call first):</span><br><span class="line">  examples/CMakeLists.txt:22 (find_package)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Boost found at E:/boost_1_66_0</span><br><span class="line">Configuring incomplete, errors occurred!</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/2018-12-29_020403.png" alt="2018-12-29_020403"></p><h3 id="原因-2"><a href="#原因-2" class="headerlink" title="原因"></a>原因</h3><p>找到了 Boost 库，但是找不到 <code>boost_system</code>、<code>boost_filesystem</code>、<code>boost_program_options</code> 这三个库。</p><h3 id="解决-2"><a href="#解决-2" class="headerlink" title="解决"></a>解决</h3><p>这个问题太坑了，最终是把 <code>E:\boost_1_66_0\stage\lib</code> 里面的那三个库（每个有四个相关库）的名字分别删掉 <code>lib</code>，如下对 <code>boost_system</code> 的修改：</p><ul><li><code>libboost_system-vc141-mt-x32-1_66.lib</code> 改为 <code>boost_system-vc141-mt-x32-1_66.lib</code></li><li><code>libboost_system-vc141-mt-gd-x32-1_66.lib</code> 改为 <code>boost_system-vc141-mt-gd-x32-1_66.lib</code></li><li><code>libboost_system-vc141-mt-x64-1_66.lib</code> 改为 <code>boost_system-vc141-mt-x64-1_66.lib</code></li><li><code>libboost_system-vc141-mt-gd-x64-1_66.lib</code> 改为 <code>boost_system-vc141-mt-gd-x64-1_66.lib</code></li></ul><p>现在终于可以生成工程文件了！</p><p>然而 VS 打开工程后编译，又有问题。</p><h2 id="error-C2065-“CV-BGR2BGRA”-未声明的标识符"><a href="#error-C2065-“CV-BGR2BGRA”-未声明的标识符" class="headerlink" title="error C2065: “CV_BGR2BGRA”: 未声明的标识符"></a>error C2065: “CV_BGR2BGRA”: 未声明的标识符</h2><p>generate-obj.vcxproj</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eos\include\eos\render\texture.hpp(101): error C2065: “CV_BGR2BGRA”: 未声明的标识符 (undeclared identifier)</span><br></pre></td></tr></table></figure><h3 id="解决-3"><a href="#解决-3" class="headerlink" title="解决"></a>解决</h3><p>这个问题可以根据这个 <a href="https://github.com/patrikhuber/4dface/issues/40">issue</a>，把 <code>CV_BGR2BGRA</code> 改为 <code>cv::COLOR_BGR2BGRA</code>，或者改为 <code>0</code> 解决。</p><h2 id="error-LNK2005-xxx-已经在-xxx-中定义；error-LNK2019-无法解析的外部符号"><a href="#error-LNK2005-xxx-已经在-xxx-中定义；error-LNK2019-无法解析的外部符号" class="headerlink" title="error LNK2005: xxx 已经在 xxx 中定义；error LNK2019: 无法解析的外部符号"></a>error LNK2005: xxx 已经在 xxx 中定义；error LNK2019: 无法解析的外部符号</h2><p>fit-model-simple.vcxproj</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">1&gt;boost_program_options-vc140-mt-gd.lib(boost_program_options-vc141-mt-gd-x32-1_68.dll) : error LNK2005: &quot;public: __thiscall boost::program_options::value_semantic_codecvt_helper&lt;char&gt;::value_semantic_codecvt_helper&lt;char&gt;(void)&quot; (??0?$value_semantic_codecvt_helper@D@program_options@boost@@QAE@XZ) 已经在 boost_program_options-vc141-mt-gd-x32-1_66.lib(value_semantic.obj) 中定义</span><br><span class="line">1&gt;boost_program_options-vc140-mt-gd.lib(boost_program_options-vc141-mt-gd-x32-1_68.dll) : error LNK2005: &quot;public: virtual __thiscall boost::program_options::value_semantic_codecvt_helper&lt;char&gt;::~value_semantic_codecvt_helper&lt;char&gt;(void)&quot; (??1?$value_semantic_codecvt_helper@D@program_options@boost@@UAE@XZ) 已经在 boost_program_options-vc141-mt-gd-x32-1_66.lib(value_semantic.obj) 中定义</span><br><span class="line">1&gt;boost_program_options-vc140-mt-gd.lib(boost_program_options-vc141-mt-gd-x32-1_68.dll) : error LNK2005: &quot;void __cdecl boost::program_options::validate(class boost::any &amp;,class std::vector&lt;class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;,class std::allocator&lt;class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; &gt; &gt; const &amp;,class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; *,int)&quot; (?validate@program_options@boost@@YAXAAVany@2@ABV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@H@Z) 已经在 boost_program_options-vc141-mt-gd-x32-1_66.lib(value_semantic.obj) 中定义</span><br><span class="line">1&gt;boost_program_options-vc140-mt-gd.lib(boost_program_options-vc141-mt-gd-x32-1_68.dll) : error LNK2005: &quot;class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; __cdecl boost::program_options::to_internal(class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; const &amp;)&quot; (?to_internal@program_options@boost@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV34@@Z) 已经在 boost_program_options-vc141-mt-gd-x32-1_66.lib(convert.obj) 中定义</span><br><span class="line">1&gt;  正在创建库 D:/code/VS/BabyCreator/eos_build/examples/Debug/fit-model-simple.lib 和对象 D:/code/VS/BabyCreator/eos_build/examples/Debug/fit-model-simple.exp</span><br><span class="line">1&gt;fit-model-simple.obj : error LNK2019: 无法解析的外部符号 &quot;class cv::Mat __cdecl cv::imread(class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; const &amp;,int)&quot; (?imread@cv@@YA?AVMat@1@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)，该符号在函数 __catch$_main$0 中被引用</span><br><span class="line">1&gt;fit-model-simple.obj : error LNK2019: 无法解析的外部符号 &quot;bool __cdecl cv::imwrite(class std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt; const &amp;,class cv::debug_build_guard::_InputArray const &amp;,class std::vector&lt;int,class std::allocator&lt;int&gt; &gt; const &amp;)&quot; (?imwrite@cv@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV_InputArray@debug_build_guard@1@ABV?$vector@HV?$allocator@H@std@@@3@@Z)，该符号在函数 __catch$_main$6 中被引用</span><br><span class="line">1&gt;D:\code\VS\BabyCreator\eos_build\examples\Debug\fit-model-simple.exe : fatal error LNK1120: 2 个无法解析的外部命令</span><br></pre></td></tr></table></figure><h3 id="原因-3"><a href="#原因-3" class="headerlink" title="原因"></a>原因</h3><p>这个问题可能是安装的这个版本的 boost 库与什么东西不兼容吧，又是环境问题，我已经无力吐槽 Windows 了（心累）。</p><h3 id="解决-4"><a href="#解决-4" class="headerlink" title="解决"></a>解决</h3><p>这个问题我在官方仓库提了个 <a href="https://github.com/patrikhuber/eos/issues/245">issue</a>。</p><p>作者的意思是：我没试过你的 boost 和 opencv 的版本，可能是本地配置问题，建议用构建系统（如 <a href="https://github.com/Microsoft/vcpkg/">vcpkg</a>） 或者在 StackOverflow 上提问。</p><p>我：emmm……</p><p>所以，这个问题未解决，最后是用 vcpkg 安装库解决的。</p><h2 id="再次编译环境"><a href="#再次编译环境" class="headerlink" title="再次编译环境"></a>再次编译环境</h2><ul><li>Windows 10</li><li>Visual Studio 2017</li><li>CMake 3.12.4</li><li>OpenCV 3.4.3</li><li>Boost 1.68.0</li><li>vcpkg 2018.11.23-nohash</li></ul><h2 id="vcpkg-配置安装"><a href="#vcpkg-配置安装" class="headerlink" title="vcpkg 配置安装"></a>vcpkg 配置安装</h2><p>安装 vcpkg、opencv、boost</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/Microsoft/vcpkg.git</span><br><span class="line">cd vcpkg</span><br><span class="line">.\bootstrap-vcpkg.bat</span><br><span class="line">.\vcpkg install opencv boost</span><br></pre></td></tr></table></figure><p>安装完成后，在 <code>eos</code> 同级目录下创建 build 文件夹 <code>eos_vcpkg_build</code>，如下目录结构：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">- eos</span><br><span class="line">  - CMakeLists.txt</span><br><span class="line">  - ...</span><br><span class="line">- eos_vcpkg_build</span><br><span class="line">  - install</span><br><span class="line">  - eos.sln</span><br><span class="line">  - ...</span><br></pre></td></tr></table></figure><p>然后执行下面的命令构建工程：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir eos_vcpkg_build</span><br><span class="line">cd eos_vcpkg_build</span><br><span class="line">cmake ../eos -DOpenCV_DIR=D:\\code\\git\\vcpkg\\buildtrees\\opencv\\x86-windows-rel -DBOOST_ROOT=D:\\code\\git\\vcpkg\\installed\\x86-windows\\bin -DBOOST_LIBRARYDIR=D:\\code\\git\\vcpkg\\installed\\x86-windows\\bin -DBOOST_INCLUDEDIR=D:\\code\\git\\vcpkg\\installed\\x86-windows\\include -DCMAKE_INSTALL_PREFIX=install/</span><br></pre></td></tr></table></figure><ul><li><code>OpenCV_DIR</code> 设为 vcpkg 安装的 <code>opencv 路径</code></li><li><code>BOOST_ROOT</code> 设为 vcpkg 安装的 <code>boost 路径</code></li><li><code>BOOST_LIBRARYDIR</code> 设为 vcpkg 安装的 <code>boost 库文件路径</code></li><li><code>BOOST_INCLUDEDIR</code> 设为 vcpkg 安装的 <code>boost 头文件路径</code></li><li><code>CMAKE_INSTALL_PREFIX</code> 即为 <code>make install 的路径</code></li></ul><p>构建好后，用 VS 打开，右键 <code>解决方案 eos</code> - <code>生成解决方案</code></p><p>然后选择 <code>INSTALL</code> 工程 - 右键 <code>设为启动项目</code> - 右键 <code>生成</code></p><p>居然成功编译并安装好了（喜极而泣）！</p><h2 id="eos-运行示例"><a href="#eos-运行示例" class="headerlink" title="eos 运行示例"></a>eos 运行示例</h2><p>运行下 <code>eos_vcpkg_build\install\bin\fit-model.exe</code> 示例程序吧 ~</p><p>根据墨菲定律，必定没这么顺利，果然……</p><p>一连跳几个框，</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">由于找不到 opencv_core343.dll、opencv_imgcodecs343.dll、boost_filesystem-vc141-mt-x32-1_68.dll、jpeg62.dll、zlib1.dll 等，无法继续执行代码。重新安装重新可能会解决此问题。</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/1546520602.jpg"></p><p>既然缺少动态库，那就去 vcpkg 安装路径下找，如果没有则用 vcpkg 安装，然后把这些 dll 放到 <code>fit-model.exe</code> 同级目录下。</p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/2019-01-03_213217.png"></p><p>然后就……</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">应用程序无法正常启动(0xc000007b)。请点击“确定”关闭应用程序。</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/2019-01-03_212959.png"></p><p>我：emmm……mmp</p><p>应该是动态库的链接错误，关于这个问题我再次开了 <a href="https://github.com/patrikhuber/eos/issues/245#issuecomment-451143760">issue</a>，但是作者不再回应了。</p><p>所以，在 Windows 上，只是编译成功库，但是示例都无法运行。</p><p>最终，在 Ubuntu 上，编译运行起来了。</p><p>心累。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/patrikhuber/eos&quot;&gt;eos&lt;/a&gt; 是一个用现代 C++11&amp;#x2F;14 编写的轻量级三维形变人脸模型拟合库，下面介绍下编译它的步骤和遇到的一些坑坑坑坑！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;博文的前半部分是用手动安装的 opencv 和 boost 构建和编译的，一路是坑，最终没有编译成功；&lt;/li&gt;
&lt;li&gt;博文的后半部分是用 &lt;a href=&quot;https://github.com/Microsoft/vcpkg/&quot;&gt;vcpkg&lt;/a&gt; 构建系统安装的 opencv 和 boost 然后构建和编译的，最终编译成功，但是运行失败。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;至今为止，关于运行失败的 &lt;a href=&quot;https://github.com/patrikhuber/eos/issues/245&quot;&gt;issue&lt;/a&gt; 作者也没有回复，希望有朝一日能填坑吧~&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="链接装载库" scheme="https://blog.huihut.com/tags/%E9%93%BE%E6%8E%A5%E8%A3%85%E8%BD%BD%E5%BA%93/"/>
    
  </entry>
  
  <entry>
    <title>Unity3D Plugin xxx is used from several locations 错误</title>
    <link href="https://blog.huihut.com/2019/01/07/Unity3DPluginXXXIsUsedFromSeveralLocations/"/>
    <id>https://blog.huihut.com/2019/01/07/Unity3DPluginXXXIsUsedFromSeveralLocations/</id>
    <published>2019-01-07T13:41:35.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<h2 id="错误"><a href="#错误" class="headerlink" title="错误"></a>错误</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Plugin &#x27;opencvforunity.dll&#x27; is used from several locations:</span><br><span class="line"> Assets/OpenCVForUnity/Plugins/x86/opencvforunity.dll would be copied to &lt;PluginPath&gt;/opencvforunity.dll</span><br><span class="line"> Assets/OpenCVForUnity/Plugins/x86_64/opencvforunity.dll would be copied to &lt;PluginPath&gt;/opencvforunity.dll</span><br><span class="line">Please fix plugin settings and try again.</span><br><span class="line"></span><br><span class="line">UnityEditor.Modules.DefaultPluginImporterExtension:CheckFileCollisions(String)</span><br><span class="line">UnityEditorInternal.PluginsHelper:CheckFileCollisions(BuildTarget) (at D:/unity/Editor/Mono/Plugins/PluginsHelper.cs:25)</span><br><span class="line">UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()</span><br></pre></td></tr></table></figure><span id="more"></span><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>我使用的 <code>opencvforunity.dll</code> 库的 32 位版本与 64 位版本在 Unity 编辑器中没有明确指定，所以 Unity 不知道 32 位或者 64 位系统下用哪个 <code>opencvforunity.dll</code> 库。</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><ul><li>为 x86 的 <code>opencvforunity.dll</code> 取消 x86_64 平台，只勾选 x86 平台，Apply</li><li>为 x86_64 的 <code>opencvforunity.dll</code> 取消 x86 平台，只勾选 x86_64 平台，Apply</li></ul><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/Unity3DOpencvforunity.dll.png" alt="Unity3DOpencvforunity.dll"></p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;错误&quot;&gt;&lt;a href=&quot;#错误&quot; class=&quot;headerlink&quot; title=&quot;错误&quot;&gt;&lt;/a&gt;错误&lt;/h2&gt;&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Plugin &amp;#x27;opencvforunity.dll&amp;#x27; is used from several locations:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Assets/OpenCVForUnity/Plugins/x86/opencvforunity.dll would be copied to &amp;lt;PluginPath&amp;gt;/opencvforunity.dll&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Assets/OpenCVForUnity/Plugins/x86_64/opencvforunity.dll would be copied to &amp;lt;PluginPath&amp;gt;/opencvforunity.dll&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Please fix plugin settings and try again.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UnityEditor.Modules.DefaultPluginImporterExtension:CheckFileCollisions(String)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UnityEditorInternal.PluginsHelper:CheckFileCollisions(BuildTarget) (at D:/unity/Editor/Mono/Plugins/PluginsHelper.cs:25)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Unity" scheme="https://blog.huihut.com/tags/Unity/"/>
    
  </entry>
  
  <entry>
    <title>Effective C++ 概要</title>
    <link href="https://blog.huihut.com/2019/01/05/EffectiveCppSummary/"/>
    <id>https://blog.huihut.com/2019/01/05/EffectiveCppSummary/</id>
    <published>2019-01-04T16:08:35.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>本文是 <a href="https://github.com/huihut/interview">huihut . C&#x2F;C++面试基础知识总结</a> 仓库的一部分，定位链接：<a href="https://github.com/huihut/interview#effective-c">Effective C++</a></p></blockquote><h3 id="Effective-C"><a href="#Effective-C" class="headerlink" title="Effective C++"></a>Effective C++</h3><ol><li>视 C++ 为一个语言联邦（C、Object-Oriented C++、Template C++、STL）</li><li>宁可以编译器替换预处理器（尽量以 <code>const</code>、<code>enum</code>、<code>inline</code> 替换 <code>#define</code>）</li><li>尽可能使用 const</li><li>确定对象被使用前已先被初始化（构造时赋值（copy 构造函数）比 default 构造后赋值（copy assignment）效率高）</li><li>了解 C++ 默默编写并调用哪些函数（编译器暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符、析构函数）</li><li>若不想使用编译器自动生成的函数，就应该明确拒绝（将不想使用的成员函数声明为 private，并且不予实现）</li><li>为多态基类声明 virtual 析构函数（如果 class 带有任何 virtual 函数，它就应该拥有一个 virtual 析构函数）</li><li>别让异常逃离析构函数（析构函数应该吞下不传播异常，或者结束程序，而不是吐出异常；如果要处理异常应该在非析构的普通函数处理）</li><li>绝不在构造和析构过程中调用 virtual 函数（因为这类调用从不下降至 derived class）</li><li>令 <code>operator=</code> 返回一个 <code>reference to *this</code> （用于连锁赋值）<span id="more"></span></li><li>在 <code>operator=</code> 中处理 “自我赋值”</li><li>赋值对象时应确保复制 “对象内的所有成员变量” 及 “所有 base class 成分”（调用基类复制构造函数）</li><li>以对象管理资源（资源在构造函数获得，在析构函数释放，建议使用智能指针，资源取得时机便是初始化时机（Resource Acquisition Is Initialization，RAII））</li><li>在资源管理类中小心 copying 行为（普遍的 RAII class copying 行为是：抑制 copying、引用计数、深度拷贝、转移底部资源拥有权（类似 auto_ptr））</li><li>在资源管理类中提供对原始资源（raw resources）的访问（对原始资源的访问可能经过显式转换或隐式转换，一般而言显示转换比较安全，隐式转换对客户比较方便）</li><li>成对使用 new 和 delete 时要采取相同形式（<code>new</code> 中使用 <code>[]</code> 则 <code>delete []</code>，<code>new</code> 中不使用 <code>[]</code> 则 <code>delete</code>）</li><li>以独立语句将 newed 对象存储于（置入）智能指针（如果不这样做，可能会因为编译器优化，导致难以察觉的资源泄漏）</li><li>让接口容易被正确使用，不易被误用（促进正常使用的办法：接口的一致性、内置类型的行为兼容；阻止误用的办法：建立新类型，限制类型上的操作，约束对象值、消除客户的资源管理责任）</li><li>设计 class 犹如设计 type，需要考虑对象创建、销毁、初始化、赋值、值传递、合法值、继承关系、转换、一般化等等。</li><li>宁以 pass-by-reference-to-const 替换 pass-by-value （前者通常更高效、避免切割问题（slicing problem），但不适用于内置类型、STL迭代器、函数对象）</li><li>必须返回对象时，别妄想返回其 reference（绝不返回 pointer 或 reference 指向一个 local stack 对象，或返回 reference 指向一个 heap-allocated 对象，或返回 pointer 或 reference 指向一个 local static 对象而有可能同时需要多个这样的对象。）</li><li>将成员变量声明为 private（为了封装、一致性、对其读写精确控制等）</li><li>宁以 non-member、non-friend 替换 member 函数（可增加封装性、包裹弹性（packaging flexibility）、机能扩充性）</li><li>若所有参数（包括被this指针所指的那个隐喻参数）皆须要类型转换，请为此采用 non-member 函数</li><li>考虑写一个不抛异常的 swap 函数</li><li>尽可能延后变量定义式的出现时间（可增加程序清晰度并改善程序效率）</li><li>尽量少做转型动作（旧式：<code>(T)expression</code>、<code>T(expression)</code>；新式：<code>const_cast&lt;T&gt;(expression)</code>、<code>dynamic_cast&lt;T&gt;(expression)</code>、<code>reinterpret_cast&lt;T&gt;(expression)</code>、<code>static_cast&lt;T&gt;(expression)</code>、；尽量避免转型、注重效率避免 dynamic_casts、尽量设计成无需转型、可把转型封装成函数、宁可用新式转型）</li><li>避免使用 handles（包括 引用、指针、迭代器）指向对象内部（以增加封装性、使 const 成员函数的行为更像 const、降低 “虚吊号码牌”（dangling handles，如悬空指针等）的可能性）</li><li>为 “异常安全” 而努力是值得的（异常安全函数（Exception-safe functions）即使发生异常也不会泄露资源或允许任何数据结构败坏，分为三种可能的保证：基本型、强列型、不抛异常型）</li><li>透彻了解 inlining 的里里外外（inlining 在大多数 C++ 程序中是编译期的行为；inline 函数是否真正 inline，取决于编译器；大部分编译器拒绝太过复杂（如带有循环或递归）的函数 inlining，而所有对 virtual 函数的调用（除非是最平淡无奇的）也都会使 inlining 落空；inline 造成的代码膨胀可能带来效率损失；inline 函数无法随着程序库的升级而升级）</li><li>将文件间的编译依存关系降至最低（如果使用 object references 或 object pointers 可以完成任务，就不要使用 objects；如果能过够，尽量以 class 声明式替换 class 定义式；为声明式和定义式提供不同的头文件）</li><li>确定你的 public 继承塑模出 is-a（是一种）关系（适用于 base classes 身上的每一件事情一定适用于 derived classes 身上，因为每一个 derived class 对象也都是一个 base class 对象）</li><li>避免遮掩继承而来的名字（可使用 using 声明式或转交函数（forwarding functions）来让被遮掩的名字再见天日）</li><li>区分接口继承和实现继承（在 public 继承之下，derived classes 总是继承 base class 的接口；pure virtual 函数只具体指定接口继承；非纯 impure virtual 函数具体指定接口继承及缺省实现继承；non-virtual 函数具体指定接口继承以及强制性实现继承）</li><li>考虑 virtual 函数以外的其他选择（如 Template Method 设计模式的 non-virtual interface（NVI）手法，将 virtual 函数替换为 “函数指针成员变量”，以 <code>tr1::function</code> 成员变量替换 virtual 函数，将继承体系内的 virtual 函数替换为另一个继承体系内的 virtual 函数）</li><li>绝不重新定义继承而来的 non-virtual 函数</li><li>绝不重新定义继承而来的缺省参数值，因为缺省参数值是静态绑定（statically bound），而 virtual 函数却是动态绑定（dynamically bound）</li><li>通过复合塑模 has-a（有一个）或 “根据某物实现出”（在应用域（application domain），复合意味 has-a（有一个）；在实现域（implementation domain），复合意味着 is-implemented-in-terms-of（根据某物实现出））</li><li>明智而审慎地使用 private 继承（private 继承意味着 is-implemented-in-terms-of（根据某物实现出），尽可能使用复合，当 derived class 需要访问 protected base class 的成员，或需要重新定义继承而来的时候 virtual 函数，或需要 empty base 最优化时，才使用 private 继承）</li><li>明智而审慎地使用多重继承（多继承比单一继承复杂，可能导致新的歧义性，以及对 virtual 继承的需要，但确有正当用途，如 “public 继承某个 interface class” 和 “private 继承某个协助实现的 class”；virtual 继承可解决多继承下菱形继承的二义性问题，但会增加大小、速度、初始化及赋值的复杂度等等成本）</li><li>了解隐式接口和编译期多态（class 和 templates 都支持接口（interfaces）和多态（polymorphism）；class 的接口是以签名为中心的显式的（explicit），多态则是通过 virtual 函数发生于运行期；template 的接口是奠基于有效表达式的隐式的（implicit），多态则是通过 template 具现化和函数重载解析（function overloading resolution）发生于编译期）</li><li>了解 typename 的双重意义（声明 template 类型参数是，前缀关键字 class 和 typename 的意义完全相同；请使用关键字 typename 标识嵌套从属类型名称，但不得在基类列（base class lists）或成员初值列（member initialization list）内以它作为 basee class 修饰符）</li><li>学习处理模板化基类内的名称（可在 derived class templates 内通过 <code>this-&gt;</code> 指涉 base class templates 内的成员名称，或藉由一个明白写出的 “base class 资格修饰符” 完成）</li><li>将与参数无关的代码抽离 templates（因类型模板参数（non-type template parameters）而造成代码膨胀往往可以通过函数参数或 class 成员变量替换 template 参数来消除；因类型参数（type parameters）而造成的代码膨胀往往可以通过让带有完全相同二进制表述（binary representations）的实现类型（instantiation types）共享实现码）</li><li>运用成员函数模板接受所有兼容类型（请使用成员函数模板（member function templates）生成 “可接受所有兼容类型” 的函数；声明 member templates 用于 “泛化 copy 构造” 或 “泛化 assignment 操作” 时还需要声明正常的 copy 构造函数和 copy assignment 操作符）</li><li>需要类型转换时请为模板定义非成员函数（当我们编写一个 class template，而它所提供之 “与此 template 相关的” 函数支持 “所有参数之隐式类型转换” 时，请将那些函数定义为 “class template 内部的 friend 函数”）</li><li>请使用 traits classes 表现类型信息（traits classes 通过 templates 和 “templates 特化” 使得 “类型相关信息” 在编译期可用，通过重载技术（overloading）实现在编译期对类型执行 if…else 测试）</li><li>认识 template 元编程（模板元编程（TMP，template metaprogramming）可将工作由运行期移往编译期，因此得以实现早期错误侦测和更高的执行效率；TMP 可被用来生成 “给予政策选择组合”（based on combinations of policy choices）的客户定制代码，也可用来避免生成对某些特殊类型并不适合的代码）</li><li>了解 new-handler 的行为（set_new_handler 允许客户指定一个在内存分配无法获得满足时被调用的函数；nothrow new 是一个颇具局限的工具，因为它只适用于内存分配（operator new），后继的构造函数调用还是可能抛出异常）</li><li>了解 new 和 delete 的合理替换时机（为了检测运用错误、收集动态分配内存之使用统计信息、增加分配和归还速度、降低缺省内存管理器带来的空间额外开销、弥补缺省分配器中的非最佳齐位、将相关对象成簇集中、获得非传统的行为）</li><li>编写 new 和 delete 时需固守常规（operator new 应该内涵一个无穷循环，并在其中尝试分配内存，如果它无法满足内存需求，就应该调用 new-handler，它也应该有能力处理 0 bytes 申请，class 专属版本则还应该处理 “比正确大小更大的（错误）申请”；operator delete 应该在收到 null 指针时不做任何事，class 专属版本则还应该处理 “比正确大小更大的（错误）申请”）</li><li>写了 placement new 也要写 placement delete（当你写一个 placement operator new，请确定也写出了对应的 placement operator delete，否则可能会发生隐微而时断时续的内存泄漏；当你声明 placement new 和 placement delete，请确定不要无意识（非故意）地遮掩了它们地正常版本）</li><li>不要轻忽编译器的警告</li><li>让自己熟悉包括 TR1 在内的标准程序库（TR1，C++ Technical Report 1，C++11 标准的草稿文件）</li><li>让自己熟悉 Boost（准标准库）</li></ol>]]></content>
    
    
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;本文是 &lt;a href=&quot;https://github.com/huihut/interview&quot;&gt;huihut . C&amp;#x2F;C++面试基础知识总结&lt;/a&gt; 仓库的一部分，定位链接：&lt;a href=&quot;https://github.com/huihut/interview#effective-c&quot;&gt;Effective C++&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Effective-C&quot;&gt;&lt;a href=&quot;#Effective-C&quot; class=&quot;headerlink&quot; title=&quot;Effective C++&quot;&gt;&lt;/a&gt;Effective C++&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;视 C++ 为一个语言联邦（C、Object-Oriented C++、Template C++、STL）&lt;/li&gt;
&lt;li&gt;宁可以编译器替换预处理器（尽量以 &lt;code&gt;const&lt;/code&gt;、&lt;code&gt;enum&lt;/code&gt;、&lt;code&gt;inline&lt;/code&gt; 替换 &lt;code&gt;#define&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;尽可能使用 const&lt;/li&gt;
&lt;li&gt;确定对象被使用前已先被初始化（构造时赋值（copy 构造函数）比 default 构造后赋值（copy assignment）效率高）&lt;/li&gt;
&lt;li&gt;了解 C++ 默默编写并调用哪些函数（编译器暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符、析构函数）&lt;/li&gt;
&lt;li&gt;若不想使用编译器自动生成的函数，就应该明确拒绝（将不想使用的成员函数声明为 private，并且不予实现）&lt;/li&gt;
&lt;li&gt;为多态基类声明 virtual 析构函数（如果 class 带有任何 virtual 函数，它就应该拥有一个 virtual 析构函数）&lt;/li&gt;
&lt;li&gt;别让异常逃离析构函数（析构函数应该吞下不传播异常，或者结束程序，而不是吐出异常；如果要处理异常应该在非析构的普通函数处理）&lt;/li&gt;
&lt;li&gt;绝不在构造和析构过程中调用 virtual 函数（因为这类调用从不下降至 derived class）&lt;/li&gt;
&lt;li&gt;令 &lt;code&gt;operator=&lt;/code&gt; 返回一个 &lt;code&gt;reference to *this&lt;/code&gt; （用于连锁赋值）</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>解决七牛云链接失效以及批量下载图片并迁移阿里云 OSS</title>
    <link href="https://blog.huihut.com/2018/11/08/SolveInvalidQiniuLinksAndDownloadImagesInBatchesAndMigrateAliOSS/"/>
    <id>https://blog.huihut.com/2018/11/08/SolveInvalidQiniuLinksAndDownloadImagesInBatchesAndMigrateAliOSS/</id>
    <published>2018-11-08T06:28:00.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>七牛云对测试域名进行回收，而我博文中图片用的链接仍然是测试域名的链接，因此导致部分链接失效，浏览器返回如下错误：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;error&quot;</span><span class="punctuation">:</span><span class="string">&quot;no such domain&quot;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><span id="more"></span><h2 id="找回图片对象"><a href="#找回图片对象" class="headerlink" title="找回图片对象"></a>找回图片对象</h2><p>经过提交工单与七牛云工程师协商，知道了失效的图片并没有丢失，可通过某些方法找回，解决办法如下：</p><ol><li>绑定自定义域名：<a href="https://developer.qiniu.com/kodo/kb/5158/how-to-transition-from-test-domain-name-to-a-custom-domain-name">如何从测试域名过渡到自定义域名</a>（绑定后则可用自定义域名访问失效的图片）</li><li>下载单个图片：<a href="https://developer.qiniu.com/kodo/tools/1300/qrsctl">命令行辅助工具(qrsctl)</a>（使用 qrsctl 工具的 get 下载），如下： <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">.\qrsctl.exe login huihut@outlook.com 123   # 假设密码为 123</span><br><span class="line">.\qrsctl.exe get temp H.png ./H.png         # 下载 temp 存储空间的 H.png 文件，保存到当前目录下</span><br></pre></td></tr></table></figure></li><li>下载多个对象<ol><li>先新建一个同区域存储空间，会分配一个新的测试域名到新空间</li><li>通过 qshell batchcopy 到有域名的同区域空间然后再进行 qdownload 下载操作：<a href="https://developer.qiniu.com/kodo/tools/1302/qshell">命令行工具(qshell)</a><ol><li><code>qshell listbucket &lt;原bucket名&gt; list.txt</code> （list 出全部文件）<br> <a href="https://github.com/qiniu/qshell/blob/master/docs/listbucket.md">https://github.com/qiniu/qshell/blob/master/docs/listbucket.md</a></li><li><code>cat list.txt | awk &#39;&#123;print $1&#125;&#39; &gt;list_final.txt</code> （ 用awk获取list结果的第一列）</li><li><code>qshell batchcopy &lt;原bucket名&gt; &lt;新bucket名&gt; list_final.txt</code> （复制到新bucket的文件和原bucket文件名一致）<br> <a href="https://github.com/qiniu/qshell/blob/master/docs/batchcopy.md">https://github.com/qiniu/qshell/blob/master/docs/batchcopy.md</a></li><li><code>qshell qdownload newfilelist.txt</code> （newfilelist.txt 为下载的配置文档）<br> <a href="https://github.com/qiniu/qshell/blob/master/docs/qdownload.md">https://github.com/qiniu/qshell/blob/master/docs/qdownload.md</a></li></ol></li></ol></li></ol><blockquote><p><a href="https://developer.qiniu.com/kodo/kb/3858/video-of-how-to-use-qrs-tools">视频教程 – qshell qrsctl qfetch 命令行工具使用</a></p></blockquote><h2 id="准备迁移阿里云-OSS"><a href="#准备迁移阿里云-OSS" class="headerlink" title="准备迁移阿里云 OSS"></a>准备迁移阿里云 OSS</h2><p>上面的解决方法中，要想继续使用七牛云存储作为图床，必须要有个实名认证的域名（解决方法一），然后绑定之</p><p>而我并没有，因此我打算把我的图片对象迁移到 <a href="https://cn.aliyun.com/product/oss">阿里云 OSS 存储</a></p><p>上们的解决方法二、三都可以，但是二非常麻烦，三需要两个存储空间，也就需要对七牛账号进行实名认证</p><p>而我又不想另外实名认证（<del>瞎折腾</del>），因此我用了第二种方法：下载单个图片！[捂脸]</p><h2 id="C-程序下载七牛存储的对象"><a href="#C-程序下载七牛存储的对象" class="headerlink" title="C++ 程序下载七牛存储的对象"></a>C++ 程序下载七牛存储的对象</h2><p>使用 qrsctl 工具只能单个文件下载，为了避免重复的工作，我写了个 C++ 程序解决。</p><h3 id="获取包含所有对象名的-html-文件"><a href="#获取包含所有对象名的-html-文件" class="headerlink" title="获取包含所有对象名的 html 文件"></a>获取包含所有对象名的 html 文件</h3><p>首先进入七牛云要下载的 bucket（存储空间）的 web 界面，把内容管理列表中全部对象显示出来（点底部加载更多直到全部显示），在 Chrome 浏览器 <code>右键</code> - <code>检查</code>，如下图，选中 <code>tbody</code> - <code>右键</code> - <code>Copy</code> - <code>Copy element</code></p><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/QiniuStorageSpaceTbody.png" alt="QiniuStorageSpaceTbody"></p><p>然后把复制到的内容保存成 <code>html.html</code> 文件，放到一个目录下，如我的 <code>D:\code\test\</code>（以下均以此目录为工程目录）</p><h3 id="下载并登录-qrsctl"><a href="#下载并登录-qrsctl" class="headerlink" title="下载并登录 qrsctl"></a>下载并登录 qrsctl</h3><p>下载 <a href="https://developer.qiniu.com/kodo/tools/1300/qrsctl">命令行辅助工具(qrsctl)</a>，保存到 <code>D:\code\test\</code> 目录，并重命名为 <code>qrsctl.exe</code></p><p>在 <code>D:\code\test\</code> 目录的 CMD 或 PowerShell 中输入如下命令登录你的七牛账号</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.\qrsctl.exe login huihut@outlook.com 123   # 假设密码为 123</span><br></pre></td></tr></table></figure><h3 id="编写批量下载程序"><a href="#编写批量下载程序" class="headerlink" title="编写批量下载程序"></a>编写批量下载程序</h3><p>在 <code>D:\code\test\</code> 下创建个 <code>QrsctlGet.cpp</code>，把下面 C++ 代码保存到刚创建的文件，修改存储空间名为你的存储空间名的名字（本文为 <code>temp</code>），用 <code>VS Code</code> 或其他工具编译运行，七牛存储的文件即会下载到同目录下。</p><p>Github 仓库：<a href="https://github.com/huihut/QrsctlGet">huihut&#x2F;QrsctlGet</a>（有 <code>QrsctlGet.Cpp</code>、<code>qrsctl.exe</code>、<code>.vscode环境</code>）</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//==============================================================</span></span><br><span class="line"><span class="comment">//  作者：huihut</span></span><br><span class="line"><span class="comment">//  邮箱：huihut@outlook.com</span></span><br><span class="line"><span class="comment">//  时间：2018-11-08 14:28:00</span></span><br><span class="line"><span class="comment">//  说明：匹配 HTML 的七牛云存储的文件名，并使用 qrsctl 下载文件</span></span><br><span class="line"><span class="comment">//==============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;regex&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">// 存储空间名【需要修改为你的存储空间名】</span></span><br><span class="line">string bucket = <span class="string">&quot;temp&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 打开 html 文件</span></span><br><span class="line">ifstream fhtml;</span><br><span class="line">fhtml.<span class="built_in">open</span>(<span class="string">&quot;html.html&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 统计下载的文件对象数</span></span><br><span class="line"><span class="type">int</span> num = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (fhtml)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// tbody 里面符合 reg 的奇数为文件对象，偶数是文件类型，因此只取奇数匹配项</span></span><br><span class="line"><span class="type">bool</span> isObj = <span class="literal">true</span>;</span><br><span class="line">std::stringstream buffer;</span><br><span class="line">buffer &lt;&lt; fhtml.<span class="built_in">rdbuf</span>();</span><br><span class="line"><span class="function">std::string <span class="title">contents</span><span class="params">(buffer.str())</span></span>;</span><br><span class="line">std::smatch match;</span><br><span class="line"><span class="function">std::regex <span class="title">reg</span><span class="params">(<span class="string">&quot;\\b(edit-word ng-binding\&quot;&gt;)([^&lt;]*)&quot;</span>)</span></span>;</span><br><span class="line"><span class="keyword">while</span> (std::<span class="built_in">regex_search</span>(contents, match, reg)) &#123;</span><br><span class="line"><span class="keyword">if</span> (isObj)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 匹配到的文件对象</span></span><br><span class="line">string objfile = match.format(<span class="string">&quot;$2&quot;</span>);</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;Matched &quot;</span> + objfile &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 合成下载命令</span></span><br><span class="line">string command = <span class="string">&quot;qrsctl.exe get &quot;</span> + bucket + <span class="string">&quot; &quot;</span> + objfile + <span class="string">&quot; ./&quot;</span> + objfile;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 下载文件</span></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;Download &quot;</span> + objfile + <span class="string">&quot;...&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="built_in">system</span>(command.<span class="built_in">c_str</span>());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 文件个数加一</span></span><br><span class="line">num++;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 下一个非文件对象</span></span><br><span class="line">isObj = <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 下一个是文件对象</span></span><br><span class="line">isObj = <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line">contents = match.<span class="built_in">suffix</span>().<span class="built_in">str</span>();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">cerr &lt;&lt; <span class="string">&quot;Failed to read html file!&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;Downloaded &quot;</span> + <span class="built_in">to_string</span>(num) + <span class="string">&quot; files.&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/QiniuQrsctlDownload.png" alt="QiniuQrsctlDownload"></p><h2 id="迁移阿里云-OSS"><a href="#迁移阿里云-OSS" class="headerlink" title="迁移阿里云 OSS"></a>迁移阿里云 OSS</h2><p>在 <a href="https://cn.aliyun.com/product/oss">阿里云 OSS 存储</a> 创建阿里云账号，并在 OSS 中新建 Bucket，其中读写权限选中公共读（public-read），以便能在博文中读取</p><p>把上面下载的图片上传到阿里云 OSS，可以使用客户端上传下载：<a href="https://github.com/aliyun/oss-browser">aliyun&#x2F;oss-browser</a></p><p>然后获取外链，批量修改我的博文，把所有七牛云链接改为阿里云就好了</p>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;起因&quot;&gt;&lt;a href=&quot;#起因&quot; class=&quot;headerlink&quot; title=&quot;起因&quot;&gt;&lt;/a&gt;起因&lt;/h2&gt;&lt;p&gt;七牛云对测试域名进行回收，而我博文中图片用的链接仍然是测试域名的链接，因此导致部分链接失效，浏览器返回如下错误：&lt;/p&gt;
&lt;figure class=&quot;highlight json&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;punctuation&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span class=&quot;attr&quot;&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class=&quot;punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&amp;quot;no such domain&amp;quot;&lt;/span&gt;&lt;span class=&quot;punctuation&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
    <category term="OSS" scheme="https://blog.huihut.com/tags/OSS/"/>
    
  </entry>
  
  <entry>
    <title>C# 解压压缩包及 7z 库缺失导致 Can not load 7-zip library or internal COM error!</title>
    <link href="https://blog.huihut.com/2018/11/07/CSharpUnzipAnd7zLibraryMissingError/"/>
    <id>https://blog.huihut.com/2018/11/07/CSharpUnzipAnd7zLibraryMissingError/</id>
    <published>2018-11-06T16:20:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="表现"><a href="#表现" class="headerlink" title="表现"></a>表现</h2><p>C# 程序解压 7z 文件的时候抛出异常</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Can not load 7-zip library or internal COM error! Message: DLL file does not exist.</span><br></pre></td></tr></table></figure><span id="more"></span><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>程序无法找到 7z 库，导致无法解压 7z 文件</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><h3 id="方法一：使用-NuGet-包管理器下载安装"><a href="#方法一：使用-NuGet-包管理器下载安装" class="headerlink" title="方法一：使用 NuGet 包管理器下载安装"></a>方法一：使用 NuGet 包管理器下载安装</h3><p>选择 Visual Studio 某个项目 - 右键引用 - 管理 NuGet 程序包 - 浏览 - 搜索 <code>7z</code>，选择一个 <code>7z</code> 包，如 <code>7z.Libs</code> 安装即可。</p><h3 id="方法二：手动下载安装"><a href="#方法二：手动下载安装" class="headerlink" title="方法二：手动下载安装"></a>方法二：手动下载安装</h3><p>在官网 <a href="https://www.7-zip.org/download.html">Download 7-Zip </a> 下载下面的 7z 库</p><table><thead><tr><th>Link</th><th>Type</th><th>Windows</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://www.7-zip.org/a/7z1805-extra.7z">Download</a></td><td>.7z</td><td>x86 &#x2F; x64</td><td>7-Zip Extra: standalone console version, 7z DLL, Plugin for Far Manager</td></tr></tbody></table><p>解压重命名到 <code>C:\Program Files\7-Zip</code></p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> 解压压缩包</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;file_path&quot;&gt;</span>压缩包路径<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;param name=&quot;save_path&quot;&gt;</span>解压后保存路径<span class="doctag">&lt;/param&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;returns&gt;</span>是否解压成功<span class="doctag">&lt;/returns&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="built_in">bool</span> <span class="title">UncompressFile</span>(<span class="params"><span class="built_in">string</span> file_path, <span class="built_in">string</span> save_path</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">try</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (System.IO.Directory.Exists(save_path))</span><br><span class="line">        &#123;</span><br><span class="line">            System.IO.Directory.Delete(save_path, <span class="literal">true</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 若手动安装，需要指定路径</span></span><br><span class="line">        <span class="comment">//SevenZip.SevenZipExtractor.SetLibraryPath(@&quot;C:\Program Files\7-Zip\7za.dll&quot;);</span></span><br><span class="line">        SevenZip.SevenZipExtractor extractor = <span class="keyword">new</span> SevenZip.SevenZipExtractor(file_path);</span><br><span class="line">        extractor.ExtractArchive(save_path);</span><br><span class="line">        extractor.Dispose();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (Exception e1)</span><br><span class="line">    &#123;</span><br><span class="line">        System.Diagnostics.Debug.WriteLine(e1.Message);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;表现&quot;&gt;&lt;a href=&quot;#表现&quot; class=&quot;headerlink&quot; title=&quot;表现&quot;&gt;&lt;/a&gt;表现&lt;/h2&gt;&lt;p&gt;C# 程序解压 7z 文件的时候抛出异常&lt;/p&gt;
&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Can not load 7-zip library or internal COM error! Message: DLL file does not exist.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Dotnet" scheme="https://blog.huihut.com/tags/Dotnet/"/>
    
    <category term="C#" scheme="https://blog.huihut.com/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>技嘉Z370 HD3P + i7-8700K + GTX1080 装黑苹果 High Sierra 10.13.6</title>
    <link href="https://blog.huihut.com/2018/10/13/GIGABYTE_Z370_HD3P_i7-8700K_GTX1080_Install_Hackintosh_HighSierra10.13.6/"/>
    <id>https://blog.huihut.com/2018/10/13/GIGABYTE_Z370_HD3P_i7-8700K_GTX1080_Install_Hackintosh_HighSierra10.13.6/</id>
    <published>2018-10-13T05:00:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本博文记录了组装台式机装黑苹果 High Sierra 10.13.6 的经历。</p><p>原本想装 Mojave 10.14 的，可惜发现在 Mojave 下还没有 GTX1080 的驱动，所以只能退而求其次装 High Sierra 了。</p><p>装 High Sierra 的过程中，第一次使用 10.13.6(17G2112) 镜像遇到个问题（下文有描述），无法进入安装界面，因此后来使用 10.13.5(17F77) 镜像装好后在 AppStore 更新 10.13.6</p><span id="more"></span><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Hackintosh-High-Sierra-10.13.6.jpeg" alt="Hackintosh-High-Sierra-10.13.6"></p><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><ul><li>主板：技嘉 Z370 HD3P</li><li>CPU：Intel Core i7-8700K</li><li>核显：Intel UHD Graphics 630</li><li>独显：七彩虹 iGame GTX1080 Vulcan X 8G</li><li>内存：海盗船复仇者 DDR4 3200 8G*2</li><li>固态硬盘：三星 SSD 970 EVO 250GB（Windows）</li><li>机械硬盘：西数 WD10EZEX 7200PPM 64M 1T（EFI + MacOS + Storage）</li><li>板载音频：Realtek ALC1220</li><li>板载网卡：Intel I219V2 PCI Express Gigabit Ethernet</li><li>USB蓝牙：绿联 CSR8891 USB蓝牙 4.0</li></ul><h2 id="文件"><a href="#文件" class="headerlink" title="文件"></a>文件</h2><p>本博文使用的一些软件工具驱动，下文则不赘述。</p><ul><li><a href="https://mirrors.dtops.cc/iso/MacOS/daliansky_macos/">带 Clover 镜像</a><ul><li>10.13.6(17G2112) 镜像：<a href="https://mirrors.dtops.cc/iso/MacOS/daliansky_macos/macOS%20High%20Sierra%2010.13.6%2817G2112%29%20Installer%20with%20Clover%204606.dmg">macOS High Sierra 10.13.6(17G2112) Installer with Clover 4606.dmg</a></li><li>10.13.5(17F77)镜像：<a href="https://mirrors.dtops.cc/iso/MacOS/daliansky_macos/macOS%20High%20Sierra%2010.13.5%2817F77%29%20Installer%20with%20Clover%204512.dmg">macOS High Sierra 10.13.5(17F77) Installer with Clover 4512.dmg</a></li></ul></li><li>EFI 分区<ul><li><a href="https://github.com/huihut/Hackintosh-Z370/tree/master/EFI">huihut . Hackintosh-Z370&#x2F;EFI</a></li></ul></li><li>工具<ul><li>U盘刻录工具 Etcher：<a href="https://etcher.io/">官网</a> | <a href="https://pan.baidu.com/s/1EAarG7mLxhI0xwQEXerUEg">百度网盘</a></li><li>Clover 配置工具 Clover Configurator：<a href="https://www.tonymacx86.com/resources/clover-configurator.335/">官网</a> | <a href="https://pan.baidu.com/s/1adKnfyIT0MVwHGl_Lke_Fg">百度网盘</a></li><li>内核注入工具 Kext Wizard：<a href="https://mac.softpedia.com/get/Utilities/Kext-Wizard.shtml">网络</a> | <a href="https://pan.baidu.com/s/1bnsRR4s3FYmc6jCRiVYRew">百度网盘</a></li><li>文本编辑器 BBEdit 12：<a href="https://www.barebones.com/products/bbedit/">官网</a> | <a href="https://pan.baidu.com/s/1pWO_hFMcHIjzoFGSOdUgDQ">百度网盘</a></li></ul></li><li>驱动<ul><li>驱动安装工具 MultiBeast 10.4.0 - High Sierra：<a href="https://www.tonymacx86.com/resources/multibeast-10-4-0-high-sierra.401/">官网</a> | <a href="https://pan.baidu.com/s/1QBX514ELiqltAJ_EcHan0g">百度网盘</a></li><li>Nvidia Web 驱动 387.10.10.10.40.105（适用于 10.13.6）：<a href="https://www.nvidia.com/download/driverResults.aspx/136062/en-us">官网</a> | <a href="https://pan.baidu.com/s/1pgf06gmxiwpK1256_7QmcQ">百度网盘</a></li><li>Nvidia Web 驱动 387.10.10.10.35.106（适用于 10.13.5）：<a href="https://www.nvidia.com/download/driverResults.aspx/134834/en-us">官网</a> | <a href="https://pan.baidu.com/s/13ObVcKgRqr1XIvDv2d96Eg">百度网盘</a></li></ul></li></ul><h2 id="刻录镜像"><a href="#刻录镜像" class="headerlink" title="刻录镜像"></a>刻录镜像</h2><p>准备一个8G以上的U盘，使用 Etcher 刻录上面下载的镜像（带有 Clover EFI 分区）：<code>macOS High Sierra 10.13.6(17G2112) Installer with Clover 4606.dmg</code></p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/etcher-create-hackintosh.png" alt="etcher-create-hackintosh"></p><h2 id="设置-BIOS"><a href="#设置-BIOS" class="headerlink" title="设置 BIOS"></a>设置 BIOS</h2><blockquote><p>BIOS 版本已更新为 F7</p></blockquote><ul><li>Save &amp; Exit -&gt; Load Optimized Defaults : Yes</li><li>M.I.T. -&gt; Advanced Memory Settings -&gt; Extreme Memory Profile(X.M.P.) : Profile 1</li><li>BIOS -&gt; Fast Boot : Disabled</li><li>BIOS -&gt; CSM Support : Disabled</li><li>Peripherals -&gt; Super IO Configuration -&gt; Serial Port : Disabled</li><li>Peripherals -&gt; USB Configuration -&gt; XHCI Hand-off : Enabled</li><li>Chipset -&gt; Vt-d : Disabled</li></ul><p>保存 BIOS 配置</p><h2 id="引导出错"><a href="#引导出错" class="headerlink" title="引导出错"></a>引导出错</h2><p>重启进入刻录好的U盘，选择 <code>Boot macOS Install from Install macOS High Sierra</code></p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/IMG_20181007_204929.jpg" alt="Clover"></p><p>唠叨模式滚代码的时候出错：please go to <a href="https://panic.apple.com/">https://panic.apple.com</a> to report this panic</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/IMG_20181007_211514.jpg" alt="please go to https://panic.apple.com to report this panic"></p><h2 id="重新刻录"><a href="#重新刻录" class="headerlink" title="重新刻录"></a>重新刻录</h2><p>上面的问题 Google 了一圈并未发现解决办法，因此重新刻录 <code>macOS High Sierra 10.13.5(17F77) Installer with Clover 4512.dmg</code>，先装 10.13.5(17F77) 。</p><h2 id="引导安装"><a href="#引导安装" class="headerlink" title="引导安装"></a>引导安装</h2><p>这次的 10.13.5(17F77)  成功进入安装界面了。</p><p>打开磁盘工具，格好一个系统盘，格式为 APFS 或者 Mac OS 扩展（日志式），大小因人而异，我留了 128G。</p><p>格好后安装系统到这个盘。</p><p>安装过程中第一次自动重启依然进入 U 盘 Clover，引导进入格出来的盘继续安装。</p><p>第二次自动重启也是进入 U 盘 Clover，引导进入格出来的盘，然后安装完毕进入系统。</p><h2 id="安装-Clover"><a href="#安装-Clover" class="headerlink" title="安装 Clover"></a>安装 Clover</h2><h3 id="Clover-选择"><a href="#Clover-选择" class="headerlink" title="Clover 选择"></a>Clover 选择</h3><p>进入系统后发现 1080 独显不能驱动、八代 CPU 不能识别，这个先不管，先装 Clover 到磁盘的 EFI 分区。</p><p>安装 Clover 有两种：</p><ul><li>使用原版 CLover：<a href="https://sourceforge.net/projects/cloverefiboot/">Clover EFI bootloader 官方下载</a></li><li>使用 U 盘 EFI 分区的 Clover</li></ul><p>由于 U 盘的 Clover 是已经试验过能引导的，所以我就用了 U 盘的。</p><h3 id="挂载-EFI-分区"><a href="#挂载-EFI-分区" class="headerlink" title="挂载 EFI 分区"></a>挂载 EFI 分区</h3><p>在终端上执行 <code>diskutil list</code>，找到两个 EFI 分区（磁盘的 EFI 和 U 盘的 EFI），如下的 <code>disk0 s1</code> 和 <code>disk3 s1</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">HuiMac:~ huihut$ diskutil list</span><br><span class="line">/dev/disk0 (internal, physical):</span><br><span class="line">   #:                       TYPE NAME                    SIZE       IDENTIFIER</span><br><span class="line">   0:      GUID_partition_scheme                        *1.0 TB     disk0</span><br><span class="line">   1:                        EFI EFI                     209.7 MB   disk0s1</span><br><span class="line">   2:                 Apple_APFS Container disk2         128.8 GB   disk0s2</span><br><span class="line">   3:       Microsoft Basic Data Document                85.9 GB    disk0s3</span><br><span class="line">   4:       Microsoft Basic Data Software                161.1 GB   disk0s4</span><br><span class="line">   5:       Microsoft Basic Data Data                    624.2 GB   disk0s5</span><br><span class="line"></span><br><span class="line">/dev/disk1 (internal):</span><br><span class="line">   #:                       TYPE NAME                    SIZE       IDENTIFIER</span><br><span class="line">   0:      GUID_partition_scheme                         250.1 GB   disk1</span><br><span class="line">   1:         Microsoft Reserved                         16.8 MB    disk1s1</span><br><span class="line">   2:       Microsoft Basic Data                         249.2 GB   disk1s2</span><br><span class="line">   3:           Windows Recovery                         847.2 MB   disk1s3</span><br><span class="line"></span><br><span class="line">/dev/disk2 (synthesized):</span><br><span class="line">   #:                       TYPE NAME                    SIZE       IDENTIFIER</span><br><span class="line">   0:      APFS Container Scheme -                      +128.8 GB   disk2</span><br><span class="line">                                 Physical Store disk0s2</span><br><span class="line">   1:                APFS Volume MacOS                   84.8 GB    disk2s1</span><br><span class="line">   2:                APFS Volume Preboot                 67.7 MB    disk2s2</span><br><span class="line">   3:                APFS Volume Recovery                1.0 GB     disk2s3</span><br><span class="line">   4:                APFS Volume VM                      20.5 KB    disk2s4</span><br><span class="line"></span><br><span class="line">/dev/disk3 (external, physical):</span><br><span class="line">   #:                       TYPE NAME                    SIZE       IDENTIFIER</span><br><span class="line">   0:      GUID_partition_scheme                        *31.0 GB    disk3</span><br><span class="line">   1:                        EFI EFI                     209.7 MB   disk3s1</span><br><span class="line">   2:                  Apple_HFS Install macOS High S... 5.7 GB     disk3s2</span><br><span class="line"></span><br><span class="line">HuiMac:~ huihut$ </span><br></pre></td></tr></table></figure><p>分别挂载到不同名字的卷</p><p>挂载磁盘 EFI</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir /Volumes/efidisk</span><br><span class="line">sudo mount -t msdos /dev/disk0s1 /Volumes/efidisk</span><br></pre></td></tr></table></figure><p>挂载 U 盘 EFI</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir /Volumes/efiusb</span><br><span class="line">sudo mount -t msdos /dev/disk3s1 /Volumes/efiusb</span><br></pre></td></tr></table></figure><h3 id="复制-Clover"><a href="#复制-Clover" class="headerlink" title="复制 Clover"></a>复制 Clover</h3><p>然后把 U 盘的 <code>EFI/CLOVER</code> 这个文件夹复制到 磁盘的 <code>EFI</code> 下 </p><h2 id="安装驱动"><a href="#安装驱动" class="headerlink" title="安装驱动"></a>安装驱动</h2><p>使用 MultiBeast 安装驱动，使用 Nvidia WebDriver 安装显卡驱动（MultiBeast 的 WebDriver 不能驱动我的 1080）。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-221705.jpg" alt="MultiBeast-config"></p><p>装好 Nvidia WebDriver 后 1080 能驱动，不过 i7-8700K 的八代 CPU 还是不能识别，先不管，在 AppStore 更新 10.13.6。</p><h2 id="更新后安装驱动"><a href="#更新后安装驱动" class="headerlink" title="更新后安装驱动"></a>更新后安装驱动</h2><p>更新完 10.13.6 发现许多驱动有问题：</p><ul><li>独显无法驱动</li><li>CPU无法识别</li><li>声卡无法驱动</li><li>USB3.0无法驱动</li></ul><h3 id="驱动独显"><a href="#驱动独显" class="headerlink" title="驱动独显"></a>驱动独显</h3><p>使用适用于 10.13.6 的 WebDriver-387.10.10.10.40.105.pkg，装好重启后就 OK 了</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Hackintosh-gpu.jpg"></p><h3 id="修复-CPU-识别"><a href="#修复-CPU-识别" class="headerlink" title="修复 CPU 识别"></a>修复 CPU 识别</h3><blockquote><p>参见 <a href="https://osx.cx/8-dai-cpu-installed-black-apple.html">八代处理器安装黑苹果 关于本机显示“未知”解决办法</a></p></blockquote><p>挂载磁盘 EFI 分区（操作如上），使用 Clover Configurator 打开 <code>/EFI/CLOVER/config.plist</code></p><p>在 CPU 页面的 Type 中填入 Unknown，保存。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-232553.jpg"></p><p>使用文本编辑器（如 BBEdit）打开 <code>/System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/Resources/zh_CN.lproj/AppleSystemInfo.strings</code> 文件</p><p>修改 <code>UnknownCPUKind</code> 的值为 <code>3.7 GHz Intel Core i7-8700K</code></p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-233544.jpg" alt="3.7 GHz Intel Core i7-8700K"></p><p>保存重启即可。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Hackintosh-system-information.jpg"></p><h3 id="修复声卡驱动"><a href="#修复声卡驱动" class="headerlink" title="修复声卡驱动"></a>修复声卡驱动</h3><blockquote><p>参见 <a href="https://imac.hk/applealc-kext-use.html">黑苹果AppleALC声卡驱动安装使用教程</a></p></blockquote><p>我使用 MultiBeast 安装的 ALC1220 驱动在 10.13.6 下不能驱动我的声卡，试过 MultiBeast 的其他驱动也不行，因此使用另一种方法修复。</p><p>在 <a href="https://github.com/acidanthera/AppleALC/releases">acidanthera&#x2F;AppleALC&#x2F;releases</a> 下载最新的 AppleALC 的 RELEASE 版 <code>AppleALC.kext</code>，使用 Kext Wizard 注入这个内核，如下图</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-225717.jpg" alt="Kext Wizard AppleALC.kext"><br><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-225733.jpg" alt="Kext Wizard AppleALC.kext"></p><p>然后挂载磁盘 EFI 分区（操作如上），把 <code>AppleALC.kext</code> 放入磁盘 EFI 分区的 <code>EFI/CLOVER/kexts/Other/</code>目录中。</p><p>然后在 <a href="https://github.com/acidanthera/AppleALC/tree/master/Resources">acidanthera&#x2F;AppleALC&#x2F;Resources</a> 找到你的声卡型号的文件夹，进入（如我的是 <code>ALC1220</code>）。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-230207.jpg" alt="ALC1220"></p><p>我的声卡型号看到有 <code>layout1.xml</code>、<code>layout2.xml</code>、<code>layout5.xml</code>、<code>layout7.xml</code>、<code>layout11.xml</code>、<code>layout13.xml</code></p><p>然后在 1、2、5、7、11、13 中随便取一个数。</p><p>使用文本编辑器打开磁盘 EFI 分区的 <code>EFI/CLOVER/config.plist</code> 文件，搜索 <code>&lt;key&gt;Audio&lt;/key&gt;</code>，把它的 <code>integer</code> 改为刚刚取的那个数（如 <code>1</code>）。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-231402.jpg" alt="Audio"></p><p>保存重启即可。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Hackintosh-audio.jpg"></p><h3 id="修复-USB3-0"><a href="#修复-USB3-0" class="headerlink" title="修复 USB3.0"></a>修复 USB3.0</h3><blockquote><p>参见 <a href="https://hackintosher.com/guides/hackintosh-high-sierra-10-13-6-update-guide/">HACKINTOSH HIGH SIERRA 10.13.6 UPDATE GUIDE</a></p></blockquote><p>使用上文描述的操作挂载磁盘的 EFI 分区</p><p>使用 Clover Configurator 打开 <code>/EFI/CLOVER/config.plist</code></p><p>如下图，插入（若已存在则修改为）配置信息</p><ul><li>Name*: com.apple.driver.usb.AppleUSBXHCI</li><li>Find* [HEX]: 837D880F 0F83A704 0000</li><li>Replace* [HEX]: 837D880F 90909090 9090</li><li>Comment: USB 10.13.6+ by PMHeart</li><li>MatchOS: 10.13.x</li></ul><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181007-223654.jpg" alt="Clover Configurator USB3.0"></p><p>保存重启即可。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/hackintosh-usb3.jpg"></p><h3 id="蓝牙免驱"><a href="#蓝牙免驱" class="headerlink" title="蓝牙免驱"></a>蓝牙免驱</h3><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Hackintosh-bluetooth.jpg"></p><h3 id="iMessage、序列号问题"><a href="#iMessage、序列号问题" class="headerlink" title="iMessage、序列号问题"></a>iMessage、序列号问题</h3><blockquote><p>参见 <a href="http://www.ituring.com.cn/article/274156">[Hackintosh]解决黑苹果无法使用Siri、iMessage等服务</a></p></blockquote><h2 id="更换Clover主题"><a href="#更换Clover主题" class="headerlink" title="更换Clover主题"></a>更换Clover主题</h2><p>Clover主题可以到官方仓库下载：</p><ul><li><a href="https://clover-wiki.zetam.org/theme-database">Clover Theme Repository</a></li></ul><p>也可以使用其他的，比如我使用这个简洁风格的：</p><ul><li><a href="https://github.com/al3xtjames/clover-theme-minimal">Clover Minimal - A clean theme for the Clover UEFI bootloader</a></li></ul><p><img src="https://camo.githubusercontent.com/df4adb0f442a1baf2ec59cf17f3442253619af6f/687474703a2f2f692e696d67626f782e636f6d2f346773734c6453492e706e67" alt="clover-theme-minimal"></p><p>只需下载下来，放到 <code>/EFI/CLOVER/themes</code> 文件夹下，然后使用 Clover Configurator 打开 <code>/EFI/CLOVER/config.plist</code> 更换到这个主题就好啦。</p><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/Jietu20181013-001702.jpg" alt="更换Clover主题"></p><p>另外这个显示启动盘的标签的 <code>Label</code> 建议勾上，这样才知道选择的是哪个盘，保存重启即可。</p><h2 id="感谢"><a href="#感谢" class="headerlink" title="感谢"></a>感谢</h2><ul><li><a href="https://www.tonymacx86.com/">tonymacx86</a></li><li><a href="https://blog.daliansky.net/">黑果小兵的部落阁</a></li><li><a href="https://imac.hk/">黑苹果乐园</a></li><li><a href="https://www.tonymacx86.com/threads/success-gigabyte-z370-hd3p-i7-8700k-gigabyte-rx580-4gb-mojave-10-14-0.256221/">[Success] Gigabyte Z370 HD3P - i7 8700K - Gigabyte RX580 4GB - Mojave 10.14.0</a></li><li><a href="https://9to5mac.com/2017/04/28/building-a-gtx-1080-ti-powered-hackintosh-installing-macos-sierra-step-by-step-video/">Building a GTX 1080 Ti-powered Hackintosh: Installing macOS Sierra step-by-step [Video]</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;本博文记录了组装台式机装黑苹果 High Sierra 10.13.6 的经历。&lt;/p&gt;
&lt;p&gt;原本想装 Mojave 10.14 的，可惜发现在 Mojave 下还没有 GTX1080 的驱动，所以只能退而求其次装 High Sierra 了。&lt;/p&gt;
&lt;p&gt;装 High Sierra 的过程中，第一次使用 10.13.6(17G2112) 镜像遇到个问题（下文有描述），无法进入安装界面，因此后来使用 10.13.5(17F77) 镜像装好后在 AppStore 更新 10.13.6&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Mac" scheme="https://blog.huihut.com/tags/Mac/"/>
    
  </entry>
  
  <entry>
    <title>pyparsing 无法卸载导致安装 matplotlib 出错</title>
    <link href="https://blog.huihut.com/2018/10/13/PyparsingFailsToUninstallCausingErrorInInstallingMatplotlib/"/>
    <id>https://blog.huihut.com/2018/10/13/PyparsingFailsToUninstallCausingErrorInInstallingMatplotlib/</id>
    <published>2018-10-13T03:02:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="表现"><a href="#表现" class="headerlink" title="表现"></a>表现</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pip install matplotlib</span><br></pre></td></tr></table></figure><p>安装 matplotlib 时出现以下错误</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> Found existing installation: pyparsing 1.5.6</span><br><span class="line">Cannot uninstall &#x27;pyparsing&#x27;. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.</span><br></pre></td></tr></table></figure><span id="more"></span><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>安装 matplotlib 需要卸载我已安装的 1.5.6 版本的 pyparsing，再重新装新版本，但是无法卸载</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>手动重装最新版 pyparsing</p><p>首先，去官网查看最新版是什么版本：<a href="https://pypi.org/project/pyparsing/">https://pypi.org/project/pyparsing/</a></p><p>当前最新版是 <code>pyparsing 2.2.0</code>，所以执行如下重新安装最新版：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pip install -I pyparsing==2.2.0</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;表现&quot;&gt;&lt;a href=&quot;#表现&quot; class=&quot;headerlink&quot; title=&quot;表现&quot;&gt;&lt;/a&gt;表现&lt;/h2&gt;&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo pip install matplotlib&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;p&gt;安装 matplotlib 时出现以下错误&lt;/p&gt;
&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt; Found existing installation: pyparsing 1.5.6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Cannot uninstall &amp;#x27;pyparsing&amp;#x27;. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Python" scheme="https://blog.huihut.com/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>python-dev 库缺失导致安装 matplotlib 出错</title>
    <link href="https://blog.huihut.com/2018/10/13/MissingPython-devCausesErrorInInstallingMatplotlib/"/>
    <id>https://blog.huihut.com/2018/10/13/MissingPython-devCausesErrorInInstallingMatplotlib/</id>
    <published>2018-10-13T03:00:00.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="表现"><a href="#表现" class="headerlink" title="表现"></a>表现</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pip install matplotlib</span><br></pre></td></tr></table></figure><p>安装 matplotlib 时出现以下错误</p><span id="more"></span><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">Installing collected packages: subprocess32, cycler, backports.functools-lru-cache, pyparsing, kiwisolver, matplotlib</span><br><span class="line">  Running setup.py install for subprocess32 ... error</span><br><span class="line">    Complete output from command /usr/bin/python2 -u -c &quot;import setuptools, tokenize;__file__=&#x27;/tmp/pip-install-azXKeu/subprocess32/setup.py&#x27;;f=getattr(tokenize, &#x27;open&#x27;, open)(__file__);code=f.read().replace(&#x27;\r\n&#x27;, &#x27;\n&#x27;);f.close();exec(compile(code, __file__, &#x27;exec&#x27;))&quot; install --record /tmp/pip-record-5SM9_6/install-record.txt --single-version-externally-managed --compile:</span><br><span class="line">    /usr/lib64/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: &#x27;python_requires&#x27;</span><br><span class="line">      warnings.warn(msg)</span><br><span class="line">    running install</span><br><span class="line">    running build</span><br><span class="line">    running build_py</span><br><span class="line">    creating build</span><br><span class="line">    creating build/lib.linux-x86_64-2.7</span><br><span class="line">    copying subprocess32.py -&gt; build/lib.linux-x86_64-2.7</span><br><span class="line">    running build_ext</span><br><span class="line">    running build_configure</span><br><span class="line">    checking for gcc... gcc</span><br><span class="line">    checking whether the C compiler works... yes</span><br><span class="line">    checking for C compiler default output file name... a.out</span><br><span class="line">    checking for suffix of executables...</span><br><span class="line">    checking whether we are cross compiling... no</span><br><span class="line">    checking for suffix of object files... o</span><br><span class="line">    checking whether we are using the GNU C compiler... yes</span><br><span class="line">    checking whether gcc accepts -g... yes</span><br><span class="line">    checking for gcc option to accept ISO C89... none needed</span><br><span class="line">    checking how to run the C preprocessor... gcc -E</span><br><span class="line">    checking for grep that handles long lines and -e... /bin/grep</span><br><span class="line">    checking for egrep... /bin/grep -E</span><br><span class="line">    checking for ANSI C header files... yes</span><br><span class="line">    checking for sys/types.h... yes</span><br><span class="line">    checking for sys/stat.h... yes</span><br><span class="line">    checking for stdlib.h... yes</span><br><span class="line">    checking for string.h... yes</span><br><span class="line">    checking for memory.h... yes</span><br><span class="line">    checking for strings.h... yes</span><br><span class="line">    checking for inttypes.h... yes</span><br><span class="line">    checking for stdint.h... yes</span><br><span class="line">    checking for unistd.h... yes</span><br><span class="line">    checking for unistd.h... (cached) yes</span><br><span class="line">    checking fcntl.h usability... yes</span><br><span class="line">    checking fcntl.h presence... yes</span><br><span class="line">    checking for fcntl.h... yes</span><br><span class="line">    checking signal.h usability... yes</span><br><span class="line">    checking signal.h presence... yes</span><br><span class="line">    checking for signal.h... yes</span><br><span class="line">    checking sys/cdefs.h usability... yes</span><br><span class="line">    checking sys/cdefs.h presence... yes</span><br><span class="line">    checking for sys/cdefs.h... yes</span><br><span class="line">    checking for sys/types.h... (cached) yes</span><br><span class="line">    checking for sys/stat.h... (cached) yes</span><br><span class="line">    checking sys/syscall.h usability... yes</span><br><span class="line">    checking sys/syscall.h presence... yes</span><br><span class="line">    checking for sys/syscall.h... yes</span><br><span class="line">    checking for dirent.h that defines DIR... yes</span><br><span class="line">    checking for library containing opendir... none required</span><br><span class="line">    checking for pipe2... yes</span><br><span class="line">    checking for setsid... yes</span><br><span class="line">    checking whether dirfd is declared... yes</span><br><span class="line">    configure: creating ./config.status</span><br><span class="line">    config.status: creating _posixsubprocess_config.h</span><br><span class="line">    building &#x27;_posixsubprocess32&#x27; extension</span><br><span class="line">    creating build/temp.linux-x86_64-2.7</span><br><span class="line">    gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python2.7 -c _posixsubprocess.c -o build/temp.linux-x86_64-2.7/_posixsubprocess.o</span><br><span class="line">    _posixsubprocess.c:16:20: fatal error: Python.h: No such file or directory</span><br><span class="line">     #include &quot;Python.h&quot;</span><br><span class="line">                        ^</span><br><span class="line">    compilation terminated.</span><br><span class="line">    error: command &#x27;gcc&#x27; failed with exit status 1</span><br></pre></td></tr></table></figure><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>无法找到 python 库，<code>#include &quot;Python.h&quot;</code> 出错</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><ul><li><p>使用 apt (Ubuntu, Debian…) 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install python-dev   # for python2.x installs</span><br><span class="line">sudo apt-get install python3-dev  # for python3.x installs</span><br></pre></td></tr></table></figure></li><li><p>使用 yum (CentOS, RHEL…) 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install python-devel   # for python2.x installs</span><br><span class="line">sudo yum install python34-devel   # for python3.4 installs</span><br></pre></td></tr></table></figure></li><li><p>使用 dnf (Fedora…) 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo dnf install python2-devel  # for python2.x installs</span><br><span class="line">sudo dnf install python3-devel  # for python3.x installs</span><br></pre></td></tr></table></figure></li><li><p>使用 zypper (openSUSE…) 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo zypper in python-devel   # for python2.x installs</span><br><span class="line">sudo zypper in python3-devel  # for python3.x installs</span><br></pre></td></tr></table></figure></li><li><p>使用 apk (Alpine…) 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apk add python2-dev  # for python2.x installs</span><br><span class="line">sudo apk add python3-dev  # for python3.x installs</span><br></pre></td></tr></table></figure></li></ul>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;表现&quot;&gt;&lt;a href=&quot;#表现&quot; class=&quot;headerlink&quot; title=&quot;表现&quot;&gt;&lt;/a&gt;表现&lt;/h2&gt;&lt;figure class=&quot;highlight plaintext&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo pip install matplotlib&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;

&lt;p&gt;安装 matplotlib 时出现以下错误&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Python" scheme="https://blog.huihut.com/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>WinRT(C++/CX) UTF8类型转换为std::string和Platform::String^的Unicode字符串</title>
    <link href="https://blog.huihut.com/2018/08/23/UTF8ToStdStrAndUTF8ToManagedStr/"/>
    <id>https://blog.huihut.com/2018/08/23/UTF8ToStdStrAndUTF8ToManagedStr/</id>
    <published>2018-08-23T15:44:50.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<p>Gist 仓库地址：<a href="https://gist.github.com/huihut/8f75e2332e05673ff7e1248ad5e85339">https://gist.github.com/huihut/8f75e2332e05673ff7e1248ad5e85339</a></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Windows.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function">std::string <span class="title">UTF8_To_Std_Str</span><span class="params">(<span class="type">const</span> std::string &amp; str)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> nwLen = <span class="built_in">MultiByteToWideChar</span>(CP_UTF8, <span class="number">0</span>, str.<span class="built_in">c_str</span>(), <span class="number">-1</span>, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">wchar_t</span>* pwBuf = <span class="keyword">new</span> <span class="type">wchar_t</span>[nwLen + <span class="number">1</span>];</span><br><span class="line"><span class="built_in">memset</span>(pwBuf, <span class="number">0</span>, nwLen * <span class="number">2</span> + <span class="number">2</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">MultiByteToWideChar</span>(CP_UTF8, <span class="number">0</span>, str.<span class="built_in">c_str</span>(), str.<span class="built_in">length</span>(), pwBuf, nwLen);</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> nLen = <span class="built_in">WideCharToMultiByte</span>(CP_ACP, <span class="number">0</span>, pwBuf, <span class="number">-1</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">char</span>* pBuf = <span class="keyword">new</span> <span class="type">char</span>[nLen + <span class="number">1</span>];</span><br><span class="line"><span class="built_in">memset</span>(pBuf, <span class="number">0</span>, nLen + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">WideCharToMultiByte</span>(CP_ACP, <span class="number">0</span>, pwBuf, nwLen, pBuf, nLen, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">std::string retStr = pBuf;</span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span>[] pBuf;</span><br><span class="line"><span class="keyword">delete</span>[] pwBuf;</span><br><span class="line"></span><br><span class="line">pBuf = <span class="literal">NULL</span>;</span><br><span class="line">pwBuf = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> retStr;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Platform::String^ <span class="built_in">UTF8_To_Managed_Str</span>(<span class="type">const</span> std::string &amp; str)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> nwLen = <span class="built_in">MultiByteToWideChar</span>(CP_UTF8, <span class="number">0</span>, str.<span class="built_in">c_str</span>(), <span class="number">-1</span>, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">wchar_t</span>* pwBuf = <span class="keyword">new</span> <span class="type">wchar_t</span>[nwLen + <span class="number">1</span>];</span><br><span class="line"><span class="built_in">memset</span>(pwBuf, <span class="number">0</span>, nwLen * <span class="number">2</span> + <span class="number">2</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">MultiByteToWideChar</span>(CP_UTF8, <span class="number">0</span>, str.<span class="built_in">c_str</span>(), str.<span class="built_in">length</span>(), pwBuf, nwLen);</span><br><span class="line"></span><br><span class="line">Platform::String^ pStr = ref <span class="keyword">new</span> Platform::<span class="built_in">String</span>(pwBuf);</span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span>[] pwBuf;</span><br><span class="line">pwBuf = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> pStr;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Gist 仓库地址：&lt;a href=&quot;https://gist.github.com/huihut/8f75e2332e05673ff7e1248ad5e85339&quot;&gt;https://gist.github.com/huihut/8f75e2332e05673ff7e124</summary>
      
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>WinRT(C++/CX) Platform::String^ 与 std::string 的类型转换</title>
    <link href="https://blog.huihut.com/2018/08/23/TypeConversionBetweenPlatformStringAndStdstring/"/>
    <id>https://blog.huihut.com/2018/08/23/TypeConversionBetweenPlatformStringAndStdstring/</id>
    <published>2018-08-23T15:43:00.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<p>Gist 仓库地址：<a href="https://gist.github.com/huihut/aa90bd3a202090e25b9a4792c80e6920">https://gist.github.com/huihut/aa90bd3a202090e25b9a4792c80e6920</a></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function">std::string <span class="title">Managed_Str_To_Std_Str</span><span class="params">(Platform::String^ ms)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">std::wstring <span class="title">w_str</span><span class="params">(ms-&gt;Begin())</span></span>;</span><br><span class="line">    <span class="keyword">return</span> std::<span class="built_in">string</span>(w_str.<span class="built_in">begin</span>(), w_str.<span class="built_in">end</span>());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Platform::String^ <span class="built_in">Std_Str_To_Managed_Str</span>(<span class="type">const</span> std::string &amp; input)</span><br><span class="line">&#123;</span><br><span class="line">    std::wstring w_str = std::<span class="built_in">wstring</span>(input.<span class="built_in">begin</span>(), input.<span class="built_in">end</span>());</span><br><span class="line">    <span class="type">const</span> <span class="type">wchar_t</span>* w_chars = w_str.<span class="built_in">c_str</span>();</span><br><span class="line">    <span class="keyword">return</span> (ref <span class="keyword">new</span> Platform::<span class="built_in">String</span>(w_chars));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Gist 仓库地址：&lt;a href=&quot;https://gist.github.com/huihut/aa90bd3a202090e25b9a4792c80e6920&quot;&gt;https://gist.github.com/huihut/aa90bd3a202090e25b9a47</summary>
      
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>OpenCV使用CMake和MinGW-w64的编译安装</title>
    <link href="https://blog.huihut.com/2018/07/31/CompiledOpenCVWithMinGW64/"/>
    <id>https://blog.huihut.com/2018/07/31/CompiledOpenCVWithMinGW64/</id>
    <published>2018-07-31T14:19:45.000Z</published>
    <updated>2023-11-03T14:37:05.670Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>之前写过的一篇博文：<a href="https://blog.huihut.com/2017/12/03/CompiledOpenCVRunInQt/">OpenCV使用CMake和MinGW的编译安装及其在Qt配置运行</a> 是使用 32 位的 MinGW 在 Windows 下编译 OpenCV 生成 32 位的 dll。</p><p>而这篇博文是使用 64 位的 MinGW 编译 OpenCV 生成 64 位的 dll。</p><p>因为博主没有 64 位 qmake，所以没勾选 <code>WITH_QT</code></p><h2 id="编译好的-OpenCV（MinGW-版）："><a href="#编译好的-OpenCV（MinGW-版）：" class="headerlink" title="编译好的 OpenCV（MinGW 版）："></a>编译好的 OpenCV（MinGW 版）：</h2><p><a href="https://github.com/huihut/OpenCV-MinGW-Build">Github . huihut&#x2F;OpenCV-MinGW-Build</a></p><span id="more"></span><h2 id="软件环境"><a href="#软件环境" class="headerlink" title="软件环境"></a>软件环境</h2><ul><li>Windows-10-64bit</li><li><a href="http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.8.1/64-bit/threads-posix/seh/x64-4.8.1-release-posix-seh-rev5.7z/download">MinGW-x64-4.8.1-release-posix-seh-rev5</a></li><li><a href="https://cmake.org/download/">CMake-3.12.0</a></li><li><a href="https://opencv.org/releases.html">OpenCV-3.4.1</a> | <a href="https://opencv.org/releases.html">OpenCV-4.0.0-alpha</a> | <a href="https://opencv.org/releases.html">OpenCV-4.0.0-rc</a> | <a href="https://opencv.org/releases.html">OpenCV-4.1.0</a></li></ul><h2 id="安装-MinGW-w64-并配置环境变量"><a href="#安装-MinGW-w64-并配置环境变量" class="headerlink" title="安装 MinGW-w64 并配置环境变量"></a>安装 MinGW-w64 并配置环境变量</h2><p>下载安装：<a href="http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.8.1/64-bit/threads-posix/seh/x64-4.8.1-release-posix-seh-rev5.7z/download">MinGW-x64-4.8.1-release-posix-seh-rev5</a></p><p>（博文使用 MinGW-x64-4.8.1 为例，但建议使用最新 MinGW：<a href="https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/">MinGW-w64 - for 32 and 64 bit Windows</a>）</p><p>为用户变量 <code>Path</code> 添加 <code>E:\MinGW-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\bin</code></p><h2 id="使环境变量生效"><a href="#使环境变量生效" class="headerlink" title="使环境变量生效"></a>使环境变量生效</h2><p>打开命令提示符 CMD，运行 <code>set PATH=C:</code>，更改当前窗口任务的环境变量，关闭这个 CMD。</p><p>再次打开另一个 CMD，运行 <code>echo %PATH%</code>，显示最新的环境变量，会发现刚刚添加的 MinGW 环境变量已经生效。</p><h2 id="使用-CMake-生成-OpenCV-的-Makefile"><a href="#使用-CMake-生成-OpenCV-的-Makefile" class="headerlink" title="使用 CMake 生成 OpenCV 的 Makefile"></a>使用 CMake 生成 OpenCV 的 Makefile</h2><p>打开 cmake-gui，设置源码和生成路径：</p><ul><li>Where is the source code: <code>E:/opencv_341/opencv/sources</code></li><li>Where to build the binaries: <code>E:/opencv_341/opencv_mingw64_build</code></li></ul><p>点击 Configure，设置编译器</p><ul><li>Specify the generator for this project: <code>MinGW Makefiles</code></li><li>Specify native compilers</li><li>Next</li><li>Compilers C: <code>E:\MinGW-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\bin\gcc.exe</code></li><li>Compilers C++: <code>E:\MinGW-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\bin\g++.exe</code></li><li>Finish</li></ul><p>编译配置：</p><ul><li>勾选 <code>WITH_OPENGL</code></li><li>勾选 <code>ENABLE_CXX11</code></li><li>不勾选 <code>WITH_IPP</code></li><li>不勾选 <code>ENABLE_PRECOMPILED_HEADERS</code></li></ul><p>点击 Configure，Generate 生成 Makefile</p><p>博主的配置信息如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br></pre></td><td class="code"><pre><span class="line">General configuration for OpenCV 3.4.1 =====================================</span><br><span class="line">  Version control:               unknown</span><br><span class="line"></span><br><span class="line">  Platform:</span><br><span class="line">    Timestamp:                   2018-07-31T02:14:11Z</span><br><span class="line">    Host:                        Windows 10.0.17134 AMD64</span><br><span class="line">    CMake:                       3.12.0</span><br><span class="line">    CMake generator:             MinGW Makefiles</span><br><span class="line">    CMake build tool:            E:/MinGW-w64/x64-4.8.1-release-posix-seh-rev5/mingw64/bin/mingw32-make.exe</span><br><span class="line">    Configuration:               Release</span><br><span class="line"></span><br><span class="line">  CPU/HW features:</span><br><span class="line">    Baseline:                    SSE SSE2 SSE3</span><br><span class="line">      requested:                 SSE3</span><br><span class="line">    Dispatched code generation:  SSE4_1 SSE4_2 FP16 AVX AVX2</span><br><span class="line">      requested:                 SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX</span><br><span class="line">      SSE4_1 (3 files):          + SSSE3 SSE4_1</span><br><span class="line">      SSE4_2 (1 files):          + SSSE3 SSE4_1 POPCNT SSE4_2</span><br><span class="line">      FP16 (2 files):            + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX</span><br><span class="line">      AVX (5 files):             + SSSE3 SSE4_1 POPCNT SSE4_2 AVX</span><br><span class="line">      AVX2 (9 files):            + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2</span><br><span class="line"></span><br><span class="line">  C/C++:</span><br><span class="line">    Built as dynamic libs?:      YES</span><br><span class="line">    C++11:                       YES</span><br><span class="line">    C++ Compiler:                E:/MinGW-w64/x64-4.8.1-release-posix-seh-rev5/mingw64/bin/g++.exe  (ver 4.8.1)</span><br><span class="line">    C++ flags (Release):         -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -Wno-long-long -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG</span><br><span class="line">    C++ flags (Debug):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -Wno-long-long -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -g  -O0 -DDEBUG -D_DEBUG</span><br><span class="line">    C Compiler:                  E:/MinGW-w64/x64-4.8.1-release-posix-seh-rev5/mingw64/bin/gcc.exe</span><br><span class="line">    C flags (Release):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-narrowing -Wno-comment -fdiagnostics-show-option -Wno-long-long -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -O3 -DNDEBUG  -DNDEBUG</span><br><span class="line">    C flags (Debug):             -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-narrowing -Wno-comment -fdiagnostics-show-option -Wno-long-long -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -g  -O0 -DDEBUG -D_DEBUG</span><br><span class="line">    Linker flags (Release):      -Wl,--gc-sections  </span><br><span class="line">    Linker flags (Debug):        -Wl,--gc-sections  </span><br><span class="line">    ccache:                      NO</span><br><span class="line">    Precompiled headers:         NO</span><br><span class="line">    Extra dependencies:          opengl32 glu32</span><br><span class="line">    3rdparty dependencies:</span><br><span class="line"></span><br><span class="line">  OpenCV modules:</span><br><span class="line">    To be built:                 calib3d core dnn features2d flann highgui imgcodecs imgproc java_bindings_generator ml objdetect photo python_bindings_generator shape stitching superres ts video videoio videostab</span><br><span class="line">    Disabled:                    js world</span><br><span class="line">    Disabled by dependency:      -</span><br><span class="line">    Unavailable:                 cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev java python2 python3 viz</span><br><span class="line">    Applications:                tests perf_tests apps</span><br><span class="line">    Documentation:               NO</span><br><span class="line">    Non-free algorithms:         NO</span><br><span class="line"></span><br><span class="line">  Windows RT support:            NO</span><br><span class="line"></span><br><span class="line">  GUI: </span><br><span class="line">    Win32 UI:                    YES</span><br><span class="line">    OpenGL support:              YES (opengl32 glu32)</span><br><span class="line">    VTK support:                 NO</span><br><span class="line"></span><br><span class="line">  Media I/O: </span><br><span class="line">    ZLib:                        build (ver 1.2.11)</span><br><span class="line">    JPEG:                        build (ver 90)</span><br><span class="line">    WEBP:                        build (ver encoder: 0x020e)</span><br><span class="line">    PNG:                         build (ver 1.6.34)</span><br><span class="line">    TIFF:                        build (ver 42 - 4.0.9)</span><br><span class="line">    JPEG 2000:                   build (ver 1.900.1)</span><br><span class="line">    OpenEXR:                     build (ver 1.7.1)</span><br><span class="line"></span><br><span class="line">  Video I/O:</span><br><span class="line">    Video for Windows:           YES</span><br><span class="line">    DC1394:                      NO</span><br><span class="line">    FFMPEG:                      YES (prebuilt binaries)</span><br><span class="line">      avcodec:                   YES (ver 57.107.100)</span><br><span class="line">      avformat:                  YES (ver 57.83.100)</span><br><span class="line">      avutil:                    YES (ver 55.78.100)</span><br><span class="line">      swscale:                   YES (ver 4.8.100)</span><br><span class="line">      avresample:                YES (ver 3.7.0)</span><br><span class="line">    GStreamer:                   NO</span><br><span class="line">    DirectShow:                  YES</span><br><span class="line"></span><br><span class="line">  Parallel framework:            none</span><br><span class="line"></span><br><span class="line">  Trace:                         YES (built-in)</span><br><span class="line"></span><br><span class="line">  Other third-party libraries:</span><br><span class="line">    Lapack:                      NO</span><br><span class="line">    Eigen:                       NO</span><br><span class="line">    Custom HAL:                  NO</span><br><span class="line">    Protobuf:                    build (3.5.1)</span><br><span class="line"></span><br><span class="line">  NVIDIA CUDA:                   NO</span><br><span class="line"></span><br><span class="line">  OpenCL:                        YES (no extra features)</span><br><span class="line">    Include path:                E:/opencv_341/opencv/sources/3rdparty/include/opencl/1.2</span><br><span class="line">    Link libraries:              Dynamic load</span><br><span class="line"></span><br><span class="line">  Python (for build):            E:/Python37-32/python.exe</span><br><span class="line"></span><br><span class="line">  Java:                          </span><br><span class="line">    ant:                         NO</span><br><span class="line">    JNI:                         C:/Program Files (x86)/Java/jdk1.8.0_181/include C:/Program Files (x86)/Java/jdk1.8.0_181/include/win32 C:/Program Files (x86)/Java/jdk1.8.0_181/include</span><br><span class="line">    Java wrappers:               NO</span><br><span class="line">    Java tests:                  NO</span><br><span class="line"></span><br><span class="line">  Matlab:                        NO</span><br><span class="line"></span><br><span class="line">  Install to:                    E:/opencv_341/opencv_mingw64_build/install</span><br><span class="line">-----------------------------------------------------------------</span><br><span class="line"></span><br><span class="line">Configuring done</span><br><span class="line">Generating done</span><br></pre></td></tr></table></figure><h2 id="编译-OpenCV"><a href="#编译-OpenCV" class="headerlink" title="编译 OpenCV"></a>编译 OpenCV</h2><p>打开终端进行编译：（<code>-j</code> 是使用 <code>8</code> 个线程进行编译，请根据你的计算机配置合理设置线程数）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">E:</span><br><span class="line">cd E:\opencv_341\opencv_mingw64_build</span><br><span class="line">mingw32-make -j 8</span><br><span class="line">mingw32-make install</span><br></pre></td></tr></table></figure><p>如果 <code>mingw32-make -j 8</code> 遇到错误，请看下面的  <strong>编译 OpenCV 常见错误</strong>，否则执行 <code>mingw32-make install</code>，完成安装。</p><h2 id="编译-OpenCV-常见错误"><a href="#编译-OpenCV-常见错误" class="headerlink" title="编译 OpenCV 常见错误"></a>编译 OpenCV 常见错误</h2><h3 id="1-MinGW-w64-的-aviriff-h-文件注释错误"><a href="#1-MinGW-w64-的-aviriff-h-文件注释错误" class="headerlink" title="1. MinGW-w64 的 aviriff.h 文件注释错误"></a>1. MinGW-w64 的 aviriff.h 文件注释错误</h3><h4 id="表现"><a href="#表现" class="headerlink" title="表现"></a>表现</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">[ 49%] Building CXX object modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_dshow.cpp.obj</span><br><span class="line">In file included from E:\opencv_341\opencv\sources\modules\videoio\src\cap_dshow.cpp:113:0:</span><br><span class="line">e:\mingw-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\x86_64-w64-mingw32\include\aviriff.h:2:8: error: expected constructor, destructor, or type conversion before &#x27;file&#x27;</span><br><span class="line"> * This file is part of the mingw-w64 runtime package.</span><br><span class="line">        ^</span><br><span class="line">e:\mingw-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\x86_64-w64-mingw32\include\aviriff.h:3:25: error: &#x27;refer&#x27; does not name a type</span><br><span class="line"> * No warranty is given; refer to the file DISCLAIMER within this package.</span><br><span class="line">                         ^</span><br><span class="line">In file included from e:\mingw-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\x86_64-w64-mingw32\include\aviriff.h:19:0,</span><br><span class="line">                 from E:\opencv_341\opencv\sources\modules\videoio\src\cap_dshow.cpp:113:</span><br><span class="line">e:\mingw-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\x86_64-w64-mingw32\include\pshpack2.h:7:21: error: expected declaration before end of line</span><br><span class="line"> #pragma pack(push,2)</span><br><span class="line">                     ^</span><br><span class="line">modules\videoio\CMakeFiles\opencv_videoio.dir\build.make:146: recipe for target &#x27;modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_dshow.cpp.obj&#x27; failed</span><br><span class="line">mingw32-make[2]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_dshow.cpp.obj] Error 1</span><br><span class="line">CMakeFiles\Makefile2:3057: recipe for target &#x27;modules/videoio/CMakeFiles/opencv_videoio.dir/all&#x27; failed</span><br><span class="line">mingw32-make[1]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/all] Error 2</span><br><span class="line">Makefile:161: recipe for target &#x27;all&#x27; failed</span><br><span class="line">mingw32-make: *** [all] Error 2</span><br></pre></td></tr></table></figure><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/MinGW-w64_aviriff.h_file_annotation_error.png" alt="MinGW-w64_aviriff.h_file_annotation_error"></p><h4 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h4><p>打开<code>E:\MinGW-w64\x64-4.8.1-release-posix-seh-rev5\mingw64\x86_64-w64-mingw32\include\aviriff.h</code></p><p>发现第一行的多行注释少了个<code>/</code>符号，加上保存，如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* This file is part of the mingw-w64 runtime package.</span></span><br><span class="line"><span class="comment">* No warranty is given; refer to the file DISCLAIMER within this package.</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><p>然后重新 <code>Configure</code>-<code>Generate</code>-<code>mingw32-make</code> 就好了。</p><h3 id="2-cap-msmf-cpp-capture-code-错误【2018年10月13日修改，因编译-OpenCV-4-0-0-alpha-时遇到并解决】"><a href="#2-cap-msmf-cpp-capture-code-错误【2018年10月13日修改，因编译-OpenCV-4-0-0-alpha-时遇到并解决】" class="headerlink" title="2. cap_msmf.cpp capture code 错误【2018年10月13日修改，因编译 OpenCV-4.0.0-alpha 时遇到并解决】"></a>2. cap_msmf.cpp capture code 错误【2018年10月13日修改，因编译 OpenCV-4.0.0-alpha 时遇到并解决】</h3><h4 id="表现-1"><a href="#表现-1" class="headerlink" title="表现"></a>表现</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp: In member function &#x27;HRESULT &#123;anonymous&#125;::ComPtr&lt;T&gt;::As(&#123;anonymous&#125;::ComPtr&lt;U&gt;&amp;) const [with U = IMF2DBuffer; T = IMFMediaBuffer; HRESULT = long int]&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp:172:5: error: control reaches end of non-void function [-Werror=return-type]</span><br><span class="line">     &#125;</span><br><span class="line">     ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp: In member function &#x27;T* &#123;anonymous&#125;::ComPtr&lt;T&gt;::operator-&gt;() const [with T = IMF2DBuffer]&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp:149:5: error: control reaches end of non-void function [-Werror=return-type]</span><br><span class="line">     &#125;</span><br><span class="line">     ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp: In member function &#x27;T* &#123;anonymous&#125;::ComPtr&lt;T&gt;::operator-&gt;() const [with T = IMFMediaBuffer]&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp:149:5: error: control reaches end of non-void function [-Werror=return-type]</span><br><span class="line">     &#125;</span><br><span class="line">     ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp: In member function &#x27;T* &#123;anonymous&#125;::ComPtr&lt;T&gt;::operator-&gt;() const [with T = IMFSinkWriter]&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp:149:5: error: control reaches end of non-void function [-Werror=return-type]</span><br><span class="line">     &#125;</span><br><span class="line">     ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp: In member function &#x27;T* &#123;anonymous&#125;::ComPtr&lt;T&gt;::Get() const [with T = IMFMediaBuffer]&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\videoio\src\cap_msmf.cpp:158:5: error: control reaches end of non-void function [-Werror=return-type]</span><br><span class="line">     &#125;</span><br><span class="line">     ^</span><br><span class="line">cc1plus.exe: some warnings being treated as errors</span><br><span class="line">modules\videoio\CMakeFiles\opencv_videoio.dir\build.make:188: recipe for target &#x27;modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_msmf.cpp.obj&#x27; failed</span><br><span class="line">mingw32-make[2]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/src/cap_msmf.cpp.obj] Error 1</span><br><span class="line">CMakeFiles\Makefile2:2556: recipe for target &#x27;modules/videoio/CMakeFiles/opencv_videoio.dir/all&#x27; failed</span><br><span class="line">mingw32-make[1]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/all] Error 2</span><br><span class="line">mingw32-make[1]: *** Waiting for unfinished jobs....</span><br><span class="line">[ 58%] Linking CXX shared library ..\..\bin\libopencv_dnn400.dll</span><br><span class="line">[ 59%] Built target opencv_dnn</span><br><span class="line">Makefile:161: recipe for target &#x27;all&#x27; failed</span><br><span class="line">mingw32-make: *** [all] Error 2</span><br></pre></td></tr></table></figure><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/20180925220634.png"></p><h4 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h4><p>因为 MinGW 不能编译 OpenCV 的 cap_msmf 那部分代码，具体见我提的 Issue：<a href="https://github.com/opencv/opencv/issues/12642">Failed to compile opencv-4.0.0-alpha using mingw-w64</a>。</p><h4 id="解决-1"><a href="#解决-1" class="headerlink" title="解决"></a>解决</h4><p>所以，在 cmake-gui 编译配置中：</p><ul><li>不勾选 <code>WITH_MSMF</code></li></ul><p>然后重新 <code>Configure</code>-<code>Generate</code>-<code>mingw32-make</code></p><h3 id="3-‘M-PI’-was-not-declared-in-this-scope-错误【2018年10月13日修改，因编译-OpenCV-4-0-0-alpha-时遇到并解决】"><a href="#3-‘M-PI’-was-not-declared-in-this-scope-错误【2018年10月13日修改，因编译-OpenCV-4-0-0-alpha-时遇到并解决】" class="headerlink" title="3. ‘M_PI’ was not declared in this scope 错误【2018年10月13日修改，因编译 OpenCV-4.0.0-alpha 时遇到并解决】"></a>3. ‘M_PI’ was not declared in this scope 错误【2018年10月13日修改，因编译 OpenCV-4.0.0-alpha 时遇到并解决】</h3><h4 id="表现-2"><a href="#表现-2" class="headerlink" title="表现"></a>表现</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">[ 86%] Building CXX object modules/calib3d/CMakeFiles/opencv_calib3d.dir/src/chessboard.cpp.obj</span><br><span class="line">In file included from E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:7:0:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.hpp: In constructor &#x27;cv::details::FastX::Parameters::Parameters()&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.hpp:35:36: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">                 resolution = float(M_PI*0.25);</span><br><span class="line">                                    ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: At global scope:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:25:42: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line"> const float MAX_ANGLE = float(48.0/180.0*M_PI);          // max angle between line segments supposed to be straight</span><br><span class="line">                                          ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:26:48: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line"> const float MIN_COS_ANGLE = float(cos(35.0/180*M_PI));   // min cos angle between board edges</span><br><span class="line">                                                ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:29:35: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line"> const float RAD2DEG = float(180.0/M_PI);</span><br><span class="line">                                   ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In function &#x27;int cv::details::testPointSymmetry(cv::Mat, cv::Point2f, float, float)&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:217:33: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">     for(double angle=0;angle &lt;= M_PI;angle+=M_PI*0.1)</span><br><span class="line">                                 ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;void cv::details::FastX::rotate(float, const cv::Mat&amp;, cv::Size, cv::Mat&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:287:110: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         cv::Mat m = cv::getRotationMatrix2D(cv::Point2f(float(img.cols*0.5),float(img.rows*0.5)),float(angle/M_PI*180),1);</span><br><span class="line">                                                                                                              ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;std::vector&lt;std::vector&lt;float&gt; &gt; cv::details::FastX::calcAngles(const std::vector&lt;cv::Mat&gt;&amp;, std::vector&lt;cv::KeyPoint&gt;&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:393:30: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">     float resolution = float(M_PI/channels);</span><br><span class="line">                              ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;void cv::details::FastX::detectImpl(const cv::Mat&amp;, std::vector&lt;cv::Mat&gt;&amp;, std::vector&lt;cv::Mat&gt;&amp;, const cv::Mat&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:631:30: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         int num = int(0.5001*M_PI/parameters.resolution);</span><br><span class="line">                              ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;void cv::details::Ellipse::draw(cv::InputOutputArray, const Scalar&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:721:43: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">     cv::ellipse(img,center,axes,360-angle/M_PI*180,0,360,color);</span><br><span class="line">                                           ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In static member function &#x27;static float cv::details::Chessboard::Board::findMaxPoint(cv::flann::Index&amp;, const cv::Mat&amp;, const cv::details::Ellipse&amp;, float, float, cv::Point2f&amp;)&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:1541:17: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         if(a1 &gt; M_PI*0.5)</span><br><span class="line">                 ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:1543:16: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         if(a2&gt; M_PI*0.5)</span><br><span class="line">                ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In static member function &#x27;static bool cv::details::Chessboard::Board::estimateSearchArea(const Point2f&amp;, const Point2f&amp;, const Point2f&amp;, float, cv::details::Ellipse&amp;, const Point2f*)&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:1787:28: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         angle = float(2.0F*M_PI-angle);</span><br><span class="line">                            ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;void cv::details::Chessboard::findKeyPoints(const cv::Mat&amp;, std::vector&lt;cv::KeyPoint&gt;&amp;, std::vector&lt;cv::Mat&gt;&amp;, std::vector&lt;std::vector&lt;float&gt; &gt;&amp;, const cv::Mat&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:2793:29: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">     para.resolution = float(M_PI*0.25);   // this gives the best results taking interpolation into account</span><br><span class="line">                             ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;cv::Mat cv::details::Chessboard::buildData(const std::vector&lt;cv::KeyPoint&gt;&amp;) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:2844:30: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         (*val++) = float(2.0*M_PI-iter-&gt;angle/180.0*M_PI);</span><br><span class="line">                              ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp: In member function &#x27;std::vector&lt;cv::KeyPoint&gt; cv::details::Chessboard::getInitialPoints(cv::flann::Index&amp;, const cv::Mat&amp;, const cv::KeyPoint&amp;, float, float, float) const&#x27;:</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:2874:25: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">         if(angle_temp &gt; M_PI*0.5)</span><br><span class="line">                         ^</span><br><span class="line">E:\opencv-4.0.0-alpha\opencv-4.0.0-alpha\modules\calib3d\src\chessboard.cpp:2879:29: error: &#x27;M_PI&#x27; was not declared in this scope</span><br><span class="line">             if(angle_temp &gt; M_PI*0.5)</span><br><span class="line">                             ^</span><br><span class="line">modules\calib3d\CMakeFiles\opencv_calib3d.dir\build.make:137: recipe for target &#x27;modules/calib3d/CMakeFiles/opencv_calib3d.dir/src/chessboard.cpp.obj&#x27; failed</span><br><span class="line">mingw32-make[2]: *** [modules/calib3d/CMakeFiles/opencv_calib3d.dir/src/chessboard.cpp.obj] Error 1</span><br><span class="line">CMakeFiles\Makefile2:3018: recipe for target &#x27;modules/calib3d/CMakeFiles/opencv_calib3d.dir/all&#x27; failed</span><br><span class="line">mingw32-make[1]: *** [modules/calib3d/CMakeFiles/opencv_calib3d.dir/all] Error 2</span><br><span class="line">Makefile:161: recipe for target &#x27;all&#x27; failed</span><br><span class="line">mingw32-make: *** [all] Error 2</span><br></pre></td></tr></table></figure><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/20180925221908.png"></p><h4 id="原因-1"><a href="#原因-1" class="headerlink" title="原因"></a>原因</h4><p>因为 OpenCV 在 <code>chessboard.cpp</code>、<code>chessboard.hpp</code>、<code>test_chesscorners.cpp</code> 这些代码中有 BUG，使用的应该是 <code>CV_PI</code> 而不是 <code>M_PI</code> 导致的。具体见我提的 Issue：<a href="https://github.com/opencv/opencv/issues/12642">Failed to compile opencv-4.0.0-alpha using mingw-w64</a></p><h4 id="解决-2"><a href="#解决-2" class="headerlink" title="解决"></a>解决</h4><ul><li><p>在最新的 master 分支已经解决了这个问题，见我的 PR ：<a href="https://github.com/opencv/opencv/pull/12645">M_PI changed to CV_PI</a></p></li><li><p>如果你是在 <a href="https://opencv.org/releases.html">官网</a> 或者 <a href="https://github.com/opencv/opencv/releases">github.com&#x2F;opencv&#x2F;opencv&#x2F;releases</a> 中下的 <code>OpenCV 4.0.0-alpha</code>，可能还会有这个问题，那么你需要把 <code>chessboard.cpp</code>、<code>chessboard.hpp</code>、<code>test_chesscorners.cpp</code> 文件中的 <code>M_PI</code> 全部改为 <code>CV_PI</code>，如我的 commit 所示：<a href="https://github.com/opencv/opencv/commit/f0d277e45246762866daea036558e2c391b39ace">M_PI changed to CV_PI (#12645)</a></p></li></ul><p>然后重新 <code>Configure</code>-<code>Generate</code>-<code>mingw32-make</code></p><h3 id="4-‘posix-memalign’-was-not-declared-in-this-scope-错误【2018年11月17日修改，因编译-OpenCV-4-0-0-rc-时遇到并解决】"><a href="#4-‘posix-memalign’-was-not-declared-in-this-scope-错误【2018年11月17日修改，因编译-OpenCV-4-0-0-rc-时遇到并解决】" class="headerlink" title="4. ‘posix_memalign’ was not declared in this scope 错误【2018年11月17日修改，因编译 OpenCV-4.0.0-rc 时遇到并解决】"></a>4. ‘posix_memalign’ was not declared in this scope 错误【2018年11月17日修改，因编译 OpenCV-4.0.0-rc 时遇到并解决】</h3><h4 id="表现-3"><a href="#表现-3" class="headerlink" title="表现"></a>表现</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[ 28%] Building CXX object modules/CMakeFiles/ade.dir/__/3rdparty/ade/ade-0.1.1c/sources/ade/source/alloc.cpp.obj</span><br><span class="line">E:\opencv-4.0.0-rc\opencv-4.0.0-rc-build\3rdparty\ade\ade-0.1.1c\sources\ade\source\alloc.cpp: In function &#x27;void* ade::aligned_alloc(std::size_t, std::size_t)&#x27;:</span><br><span class="line">E:\opencv-4.0.0-rc\opencv-4.0.0-rc-build\3rdparty\ade\ade-0.1.1c\sources\ade\source\alloc.cpp:31:16: error: &#x27;posix_memalign&#x27; was not declared in this scope</span><br><span class="line">     auto res = posix_memalign(&amp;ret, std::max(sizeof(void*), alignment), size);</span><br><span class="line">                ^~~~~~~~~~~~~~</span><br><span class="line">mingw32-make[2]: *** [modules\CMakeFiles\ade.dir\build.make:63: modules/CMakeFiles/ade.dir/__/3rdparty/ade/ade-0.1.1c/sources/ade/source/alloc.cpp.obj] Error 1</span><br><span class="line">mingw32-make[1]: *** [CMakeFiles\Makefile2:884: modules/CMakeFiles/ade.dir/all] Error 2</span><br><span class="line">mingw32-make: *** [Makefile:162: all] Error 2</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/2018-11-17_174118.png" alt="2018-11-17_174118.png"></p><h4 id="原因-2"><a href="#原因-2" class="headerlink" title="原因"></a>原因</h4><p>因为我使用了 <code>MinGW-w64-8.1.0</code> 编译，而新的编译器在 Windows 下不再定义 <code>WIN32</code>，而定义成 <code>_WIN32</code>，如这个 Issue 的问题：<a href="https://github.com/opencv/opencv/issues/12831">error: ‘posix_memalign’ was not declared in this scope #12831</a></p><h4 id="解决-3"><a href="#解决-3" class="headerlink" title="解决"></a>解决</h4><p>把 <code>opencv-4.0.0-rc-build\3rdparty\ade\ade-0.1.1c\sources\ade\source\alloc.cpp</code> 文件的所有 <code>WIN32</code> 改为 <code>_WIN32</code>，如这个 PR 所做的修改：<a href="https://github.com/opencv/ade/pull/6/files">fix check for win32 #6</a></p><p>然后重新 <code>Configure</code>-<code>Generate</code>-<code>mingw32-make</code></p><h3 id="5-‘D3D11-TEXTURE2D-DESC’-was-not-declared-in-this-scope-错误【2019年4月10日修改，因编译-OpenCV-4-1-0-时遇到并解决】"><a href="#5-‘D3D11-TEXTURE2D-DESC’-was-not-declared-in-this-scope-错误【2019年4月10日修改，因编译-OpenCV-4-1-0-时遇到并解决】" class="headerlink" title="5. ‘D3D11_TEXTURE2D_DESC’ was not declared in this scope 错误【2019年4月10日修改，因编译 OpenCV-4.1.0 时遇到并解决】"></a>5. ‘D3D11_TEXTURE2D_DESC’ was not declared in this scope 错误【2019年4月10日修改，因编译 OpenCV-4.1.0 时遇到并解决】</h3><h4 id="表现-4"><a href="#表现-4" class="headerlink" title="表现"></a>表现</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[ 32%] Building CXX object modules/core/CMakeFiles/opencv_core.dir/src/directx.cpp.obj</span><br><span class="line">E:\opencv-4.1.0\opencv-4.1.0\modules\core\src\directx.cpp: In function &#x27;void cv::directx::__convertToD3D11Texture2DNV(cv::InputAray, ID3D11Texture2D*)&#x27;:</span><br><span class="line">E:\opencv-4.1.0\opencv-4.1.0\modules\core\src\directx.cpp:1035:5: error: &#x27;D3D11_TEXTURE2D_DESC&#x27; was not declared in this scope</span><br><span class="line">     D3D11_TEXTURE2D_DESC desc = &#123; 0 &#125;;</span><br><span class="line">     ^~~~~~~~~~~~~~~~~~~~</span><br></pre></td></tr></table></figure><p><img src="https://huihut-img.oss-cn-shenzhen.aliyuncs.com/MinGW-w64_D3D11_TEXTURE2D_DESC_Error.png" alt="MinGW-w64_D3D11_TEXTURE2D_DESC_Error.png"></p><h4 id="原因-3"><a href="#原因-3" class="headerlink" title="原因"></a>原因</h4><p><code>D3D11_TEXTURE2D_DESC</code> 在 <code>d3d11.h</code> 中定义，貌似在我的机器上找不到定义。反正也不用 D3D11  与 OpenCL 交互，因此可以关闭 <code>WITH_OPENCL_D3D11_NV </code> 这个选项（默认是开的）。可见我的 issue：<a href="https://github.com/opencv/opencv/issues/14286">Error compiling 4.1.0 source code with mingw-w64: ‘D3D11_TEXTURE2D_DESC’ was not declared in this scope #14286</a></p><h4 id="解决-4"><a href="#解决-4" class="headerlink" title="解决"></a>解决</h4><p>方法一：</p><p>在 cmake-gui 编译配置中：</p><ul><li>不勾选 <code>WITH_OPENCL_D3D11_NV </code></li></ul><p>然后重新 <code>Configure</code>-<code>Generate</code>-<code>mingw32-make</code></p><p>方法二：</p><p>如这个 PR 中对这两个 cmake 文件的修改：<a href="https://github.com/opencv/opencv/pull/14294/files">cmake: fix WITH_OPENCL_D3D11_NV check #14294</a>，即可先判断是否可以用，再设置默认的 <code>WITH_OPENCL_D3D11_NV</code></p><h3 id="其他错误"><a href="#其他错误" class="headerlink" title="其他错误"></a>其他错误</h3><p>如果以上错误不是你所遇到的，请务必先看下面两个文章中的错误。</p><ul><li><a href="https://blog.huihut.com/2017/12/03/CompiledOpenCVRunInQt/">编译 32位 OpenCV 博文的常见错误</a></li><li><a href="http://visp-doc.inria.fr/doxygen/visp-daily/tutorial-install-win10-mingw64.html">Tutorial: Installation from source for Windows with Mingw-w64</a></li></ul><h2 id="更新日志"><a href="#更新日志" class="headerlink" title="更新日志"></a>更新日志</h2><ol><li>2018年10月13日为 OpenCV-4.0.0-alpha 而修改，主要改了 “编译 OpenCV 常见错误”</li><li>2018年11月17日为 OpenCV-4.0.0-rc 而修改，主要改了 “编译 OpenCV 常见错误”</li><li>2019年4月10日为 OpenCV-4.1.0 而修改，主要改了 “编译 OpenCV 常见错误”</li></ol>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;之前写过的一篇博文：&lt;a href=&quot;https://blog.huihut.com/2017/12/03/CompiledOpenCVRunInQt/&quot;&gt;OpenCV使用CMake和MinGW的编译安装及其在Qt配置运行&lt;/a&gt; 是使用 32 位的 MinGW 在 Windows 下编译 OpenCV 生成 32 位的 dll。&lt;/p&gt;
&lt;p&gt;而这篇博文是使用 64 位的 MinGW 编译 OpenCV 生成 64 位的 dll。&lt;/p&gt;
&lt;p&gt;因为博主没有 64 位 qmake，所以没勾选 &lt;code&gt;WITH_QT&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;编译好的-OpenCV（MinGW-版）：&quot;&gt;&lt;a href=&quot;#编译好的-OpenCV（MinGW-版）：&quot; class=&quot;headerlink&quot; title=&quot;编译好的 OpenCV（MinGW 版）：&quot;&gt;&lt;/a&gt;编译好的 OpenCV（MinGW 版）：&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/huihut/OpenCV-MinGW-Build&quot;&gt;Github . huihut&amp;#x2F;OpenCV-MinGW-Build&lt;/a&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="链接装载库" scheme="https://blog.huihut.com/tags/%E9%93%BE%E6%8E%A5%E8%A3%85%E8%BD%BD%E5%BA%93/"/>
    
  </entry>
  
  <entry>
    <title>Linux 下 CLion 编写调用 C++ 共享库</title>
    <link href="https://blog.huihut.com/2018/07/20/WritingCppSharedLibraryOnLinuxCLion/"/>
    <id>https://blog.huihut.com/2018/07/20/WritingCppSharedLibraryOnLinuxCLion/</id>
    <published>2018-07-20T14:35:10.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<h2 id="编写-MySharedLib-共享库"><a href="#编写-MySharedLib-共享库" class="headerlink" title="编写 MySharedLib 共享库"></a>编写 MySharedLib 共享库</h2><p>创建一个名为 MySharedLib 的共享库</p><p>CMakeLists.txt</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"><span class="keyword">project</span>(MySharedLib)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_library</span>(MySharedLib SHARED library.cpp library.h)</span><br></pre></td></tr></table></figure><span id="more"></span><p>library.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> MYSHAREDLIB_LIBRARY_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> MYSHAREDLIB_LIBRARY_H</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 打印 Hello World!</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">hello</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用可变模版参数求和</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function">T <span class="title">sum</span><span class="params">(T t)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> t;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> ...Types&gt;</span><br><span class="line"><span class="function">T <span class="title">sum</span><span class="params">(T first, Types ... rest)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> first + <span class="built_in">sum</span>&lt;T&gt;(rest...);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure><p>library.cpp</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;library.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">hello</span><span class="params">()</span> </span>&#123;</span><br><span class="line">std::cout &lt;&lt; <span class="string">&quot;Hello, World!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="被-TestSharedLib-可执行项目调用"><a href="#被-TestSharedLib-可执行项目调用" class="headerlink" title="被 TestSharedLib 可执行项目调用"></a>被 TestSharedLib 可执行项目调用</h2><p>创建一个名为 TestSharedLib 的可执行项目</p><p>CMakeLists.txt</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.10</span>)</span><br><span class="line"><span class="keyword">project</span>(TestSharedLib)</span><br><span class="line"></span><br><span class="line"><span class="comment"># C++11 编译</span></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">11</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 头文件路径</span></span><br><span class="line"><span class="keyword">set</span>(INC_DIR /home/xx/code/clion/MySharedLib)</span><br><span class="line"><span class="comment"># 库文件路径</span></span><br><span class="line"><span class="keyword">set</span>(LIB_DIR /home/xx/code/clion/MySharedLib/cmake-build-debug)</span><br><span class="line"></span><br><span class="line"><span class="keyword">include_directories</span>(<span class="variable">$&#123;INC_DIR&#125;</span>)</span><br><span class="line"><span class="keyword">link_directories</span>(<span class="variable">$&#123;LIB_DIR&#125;</span>)</span><br><span class="line"><span class="keyword">link_libraries</span>(MySharedLib)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_executable</span>(TestSharedLib main.cpp)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 链接 MySharedLib 库</span></span><br><span class="line"><span class="keyword">target_link_libraries</span>(TestSharedLib MySharedLib)</span><br></pre></td></tr></table></figure><p>main.cpp</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;library.h&quot;</span></span></span><br><span class="line"><span class="keyword">using</span> std::cout;</span><br><span class="line"><span class="keyword">using</span> std::endl;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="built_in">hello</span>();</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;1 + 2 = &quot;</span> &lt;&lt; <span class="built_in">sum</span>(<span class="number">1</span>,<span class="number">2</span>) &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;1 + 2 + 3 = &quot;</span> &lt;&lt; <span class="built_in">sum</span>(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行结果</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Hello, World!</span><br><span class="line">1 + 2 = 3</span><br><span class="line">1 + 2 + 3 = 6</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;编写-MySharedLib-共享库&quot;&gt;&lt;a href=&quot;#编写-MySharedLib-共享库&quot; class=&quot;headerlink&quot; title=&quot;编写 MySharedLib 共享库&quot;&gt;&lt;/a&gt;编写 MySharedLib 共享库&lt;/h2&gt;&lt;p&gt;创建一个名为 MySharedLib 的共享库&lt;/p&gt;
&lt;p&gt;CMakeLists.txt&lt;/p&gt;
&lt;figure class=&quot;highlight cmake&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;cmake_minimum_required&lt;/span&gt;(VERSION &lt;span class=&quot;number&quot;&gt;3.10&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;project&lt;/span&gt;(MySharedLib)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;set&lt;/span&gt;(CMAKE_CXX_STANDARD &lt;span class=&quot;number&quot;&gt;11&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;add_library&lt;/span&gt;(MySharedLib SHARED library.cpp library.h)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="C/C++" scheme="https://blog.huihut.com/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>UWP 动画改变控件大小（高度）</title>
    <link href="https://blog.huihut.com/2018/07/18/UWPAnimationChangesControlHeight/"/>
    <id>https://blog.huihut.com/2018/07/18/UWPAnimationChangesControlHeight/</id>
    <published>2018-07-18T15:09:46.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<p>有这样一个需求：</p><ul><li>鼠标移动到（悬停在）控件上（PointerEntered），控件大小（高度）发生变化，以显示更多内容；</li><li>鼠标移出控件（PointerExited），控件大小恢复原状。</li></ul><p>本文通过 UWP 动画，用两种方法实现这个效果，用于改变周贡献榜和粉丝榜的 Grid 的高度。</p><span id="more"></span><h2 id="方法一：XAML-实现动画"><a href="#方法一：XAML-实现动画" class="headerlink" title="方法一：XAML 实现动画"></a>方法一：XAML 实现动画</h2><h3 id="XAML："><a href="#XAML：" class="headerlink" title="XAML："></a>XAML：</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">UserControl.Resources</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--周贡、粉丝榜下拉恢复动画--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Storyboard</span> <span class="attr">x:Name</span>=<span class="string">&quot;SeeMoreAnimation&quot;</span> <span class="attr">Storyboard.TargetName</span>=<span class="string">&quot;WeekFansGrid&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">DoubleAnimation</span> <span class="attr">Duration</span>=<span class="string">&quot;0:0:0.2&quot;</span> <span class="attr">EnableDependentAnimation</span>=<span class="string">&quot;True&quot;</span> <span class="attr">Storyboard.TargetProperty</span>=<span class="string">&quot;Height&quot;</span> <span class="attr">From</span>=<span class="string">&quot;140&quot;</span> <span class="attr">To</span>=<span class="string">&quot;400&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">Storyboard</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Storyboard</span> <span class="attr">x:Name</span>=<span class="string">&quot;RestoreAnimation&quot;</span> <span class="attr">Storyboard.TargetName</span>=<span class="string">&quot;WeekFansGrid&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">DoubleAnimation</span>  <span class="attr">Duration</span>=<span class="string">&quot;0:0:0.2&quot;</span> <span class="attr">EnableDependentAnimation</span>=<span class="string">&quot;True&quot;</span> <span class="attr">Storyboard.TargetProperty</span>=<span class="string">&quot;Height&quot;</span> <span class="attr">From</span>=<span class="string">&quot;400&quot;</span> <span class="attr">To</span>=<span class="string">&quot;140&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">Storyboard</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">UserControl.Resources</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">Grid</span> <span class="attr">x:Name</span>=<span class="string">&quot;WeekFansGrid&quot;</span> <span class="attr">Background</span>=<span class="string">&quot;White&quot;</span> <span class="attr">VerticalAlignment</span>=<span class="string">&quot;Top&quot;</span> <span class="attr">Height</span>=<span class="string">&quot;140&quot;</span></span></span><br><span class="line"><span class="tag">              <span class="attr">PointerEntered</span>=<span class="string">&quot;Grid_PointerEntered&quot;</span> <span class="attr">PointerExited</span>=<span class="string">&quot;Grid_PointerExited&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--Grid 里面的一些内容--&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">Grid</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="C-："><a href="#C-：" class="headerlink" title="C#："></a>C#：</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 鼠标悬停周贡、粉丝榜的 Grid</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">Grid_PointerEntered</span>(<span class="params"><span class="built_in">object</span> sender, PointerRoutedEventArgs e</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">try</span></span><br><span class="line">    &#123;</span><br><span class="line">        SeeMoreAnimation.Begin();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (Exception e1)</span><br><span class="line">    &#123;</span><br><span class="line">        System.Diagnostics.Debug.WriteLine(<span class="string">&quot;Grid_PointerEntered &quot;</span> + e1.Message.ToString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 鼠标离开周贡、粉丝榜的 Grid</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">Grid_PointerExited</span>(<span class="params"><span class="built_in">object</span> sender, PointerRoutedEventArgs e</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">try</span></span><br><span class="line">    &#123;</span><br><span class="line">        RestoreAnimation.Begin();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (Exception e1)</span><br><span class="line">    &#123;</span><br><span class="line">        System.Diagnostics.Debug.WriteLine(<span class="string">&quot;Grid_PointerExited &quot;</span> + e1.Message.ToString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="方法二：后台实现动画"><a href="#方法二：后台实现动画" class="headerlink" title="方法二：后台实现动画"></a>方法二：后台实现动画</h2><h3 id="XAML：-1"><a href="#XAML：-1" class="headerlink" title="XAML："></a>XAML：</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Grid</span> <span class="attr">x:Name</span>=<span class="string">&quot;WeekFansGrid&quot;</span> <span class="attr">Background</span>=<span class="string">&quot;White&quot;</span> <span class="attr">VerticalAlignment</span>=<span class="string">&quot;Top&quot;</span> <span class="attr">Height</span>=<span class="string">&quot;140&quot;</span></span></span><br><span class="line"><span class="tag">              <span class="attr">PointerEntered</span>=<span class="string">&quot;Grid_PointerEntered&quot;</span> <span class="attr">PointerExited</span>=<span class="string">&quot;Grid_PointerExited&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--Grid 里面的一些内容--&gt;</span>     </span><br><span class="line"><span class="tag">&lt;/<span class="name">Grid</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="C-：-1"><a href="#C-：-1" class="headerlink" title="C#："></a>C#：</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 鼠标悬停周贡、粉丝榜的 Grid</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">Grid_PointerEntered</span>(<span class="params"><span class="built_in">object</span> sender, PointerRoutedEventArgs e</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">try</span></span><br><span class="line">    &#123;</span><br><span class="line">        Grid grid = sender <span class="keyword">as</span> Grid;</span><br><span class="line">        <span class="keyword">if</span> (grid != <span class="literal">null</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            DoubleAnimation SeeMoreAnimation = <span class="keyword">new</span> DoubleAnimation();</span><br><span class="line">            <span class="keyword">if</span> (SeeMoreAnimation != <span class="literal">null</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// 高度从 140 变化到 400</span></span><br><span class="line">                SeeMoreAnimation.From = <span class="number">140</span>;</span><br><span class="line">                SeeMoreAnimation.To = <span class="number">400</span>;</span><br><span class="line">                <span class="comment">// 用时 200 毫秒</span></span><br><span class="line">                SeeMoreAnimation.Duration = <span class="keyword">new</span> Duration(TimeSpan.FromMilliseconds(<span class="number">200</span>));</span><br><span class="line">                SeeMoreAnimation.EnableDependentAnimation = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 目标 Grid 的 Height</span></span><br><span class="line">                Storyboard.SetTarget(SeeMoreAnimation, grid);</span><br><span class="line">                Storyboard.SetTargetProperty(SeeMoreAnimation, <span class="string">&quot;Height&quot;</span>);</span><br><span class="line"></span><br><span class="line">                Storyboard storyboard = <span class="keyword">new</span> Storyboard();</span><br><span class="line">                <span class="keyword">if</span> (storyboard != <span class="literal">null</span>)</span><br><span class="line">                &#123;</span><br><span class="line">                    storyboard.Children.Add(SeeMoreAnimation);</span><br><span class="line">                    <span class="comment">// 执行动画</span></span><br><span class="line">                    storyboard.Begin();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (Exception e1)</span><br><span class="line">    &#123;</span><br><span class="line">        System.Diagnostics.Debug.WriteLine(<span class="string">&quot;Grid_PointerEntered &quot;</span> + e1.Message.ToString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 鼠标离开周贡、粉丝榜的 Grid</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">Grid_PointerExited</span>(<span class="params"><span class="built_in">object</span> sender, PointerRoutedEventArgs e</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">try</span></span><br><span class="line">    &#123;</span><br><span class="line">        Grid grid = sender <span class="keyword">as</span> Grid;</span><br><span class="line">        <span class="keyword">if</span> (grid != <span class="literal">null</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            DoubleAnimation SeeMoreAnimation = <span class="keyword">new</span> DoubleAnimation();</span><br><span class="line">            <span class="keyword">if</span> (SeeMoreAnimation != <span class="literal">null</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// 高度从 400 变化到 140</span></span><br><span class="line">                SeeMoreAnimation.From = <span class="number">400</span>;</span><br><span class="line">                SeeMoreAnimation.To = <span class="number">140</span>;</span><br><span class="line">                <span class="comment">// 用时 200 毫秒</span></span><br><span class="line">                SeeMoreAnimation.Duration = <span class="keyword">new</span> Duration(TimeSpan.FromMilliseconds(<span class="number">200</span>));</span><br><span class="line">                SeeMoreAnimation.EnableDependentAnimation = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 目标 Grid 的 Height</span></span><br><span class="line">                Storyboard.SetTarget(SeeMoreAnimation, grid);</span><br><span class="line">                Storyboard.SetTargetProperty(SeeMoreAnimation, <span class="string">&quot;Height&quot;</span>);</span><br><span class="line"></span><br><span class="line">                Storyboard storyboard = <span class="keyword">new</span> Storyboard();</span><br><span class="line">                <span class="keyword">if</span> (storyboard != <span class="literal">null</span>)</span><br><span class="line">                &#123;</span><br><span class="line">                    storyboard.Children.Add(SeeMoreAnimation);</span><br><span class="line">                    <span class="comment">// 执行动画</span></span><br><span class="line">                    storyboard.Begin();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">catch</span> (Exception e1)</span><br><span class="line">    &#123;</span><br><span class="line">        System.Diagnostics.Debug.WriteLine(<span class="string">&quot;Grid_PointerExited &quot;</span> + e1.Message.ToString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="实现效果"><a href="#实现效果" class="headerlink" title="实现效果"></a>实现效果</h2><p><img src="http://huihut-img.oss-cn-shenzhen.aliyuncs.com/GridSeeMoreAnimation1.gif" alt="GridSeeMoreAnimation"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;有这样一个需求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;鼠标移动到（悬停在）控件上（PointerEntered），控件大小（高度）发生变化，以显示更多内容；&lt;/li&gt;
&lt;li&gt;鼠标移出控件（PointerExited），控件大小恢复原状。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本文通过 UWP 动画，用两种方法实现这个效果，用于改变周贡献榜和粉丝榜的 Grid 的高度。&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Dotnet" scheme="https://blog.huihut.com/tags/Dotnet/"/>
    
    <category term="UWP" scheme="https://blog.huihut.com/tags/UWP/"/>
    
  </entry>
  
  <entry>
    <title>Python 生成带标签数据集的 CSV 文件</title>
    <link href="https://blog.huihut.com/2018/06/17/UsingPythonToCreateCSV/"/>
    <id>https://blog.huihut.com/2018/06/17/UsingPythonToCreateCSV/</id>
    <published>2018-06-17T15:48:32.000Z</published>
    <updated>2023-11-03T14:37:05.671Z</updated>
    
    <content type="html"><![CDATA[<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python</span></span><br><span class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Python 生成 CSV 文件</span></span><br><span class="line"><span class="comment"># Python 生成 CSV 文件，可用于生成带标签的数据集 CSV 文件，标签从0开始自动升序：0,1,2,3...</span></span><br><span class="line"><span class="comment"># 作者：huihut</span></span><br><span class="line"><span class="comment"># 仓库：https://gist.github.com/huihut/9881c98a1d9279d4fa9dfd8475e3fe4b</span></span><br><span class="line"><span class="comment"># 参考：https://github.com/opencv/opencv_attic/blob/master/opencv/modules/contrib/doc/facerec/src/create_csv.py</span></span><br><span class="line"></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">使用脚本：</span></span><br><span class="line"><span class="string">* python create_csv.py &lt;base_path&gt; [save_path]</span></span><br><span class="line"><span class="string">例如：</span></span><br><span class="line"><span class="string">* python create_csv.py /Users/xx/code/dataset</span></span><br><span class="line"><span class="string">* python create_csv.py /Users/xx/code/dataset ./dataset_csv.txt</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">目录结构（使用 tree 命令查看）：</span></span><br><span class="line"><span class="string">xx@xxs-MacBook-Pro:~/code/dataset$ tree</span></span><br><span class="line"><span class="string">.</span></span><br><span class="line"><span class="string">├── README</span></span><br><span class="line"><span class="string">├── dataset_csv.txt</span></span><br><span class="line"><span class="string">├── s01</span></span><br><span class="line"><span class="string">│   ├── 01.pgm</span></span><br><span class="line"><span class="string">│   ├── ...</span></span><br><span class="line"><span class="string">│   └── 10.pgm</span></span><br><span class="line"><span class="string">├── s02</span></span><br><span class="line"><span class="string">│   ├── 01.pgm</span></span><br><span class="line"><span class="string">│   ├── ...</span></span><br><span class="line"><span class="string">│   └── 10.pgm</span></span><br><span class="line"><span class="string">...</span></span><br><span class="line"><span class="string">└── s10</span></span><br><span class="line"><span class="string">    ├── 01.pgm</span></span><br><span class="line"><span class="string">    ├── ...</span></span><br><span class="line"><span class="string">    └── 10.pgm</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">生成的 CSV 文件内容（使用 cat 命令查看 dataset_csv.txt 文件内容）：</span></span><br><span class="line"><span class="string">xx@xxs-MacBook-Pro:~/code/dataset$ cat dataset_csv.txt</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s01/01.pgm;0</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s01/02.pgm;0</span></span><br><span class="line"><span class="string">...</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s01/10.pgm;0</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s02/01.pgm;1</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s02/02.pgm;1</span></span><br><span class="line"><span class="string">...</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s10/01.pgm;9</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s10/02.pgm;9</span></span><br><span class="line"><span class="string">...</span></span><br><span class="line"><span class="string">/Users/xx/code/dataset/s10/10.pgm;9</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> os.path</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    </span><br><span class="line">    SAVE_PATH = <span class="string">&quot;./dataset_csv.txt&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">len</span>(sys.argv) != <span class="number">2</span> <span class="keyword">and</span> <span class="built_in">len</span>(sys.argv) != <span class="number">3</span>):</span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;usage:&quot;</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;* python create_csv.py &lt;base_path&gt; [save_path]&quot;</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;example:&quot;</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;* python create_csv.py /Users/xx/code/dataset&quot;</span></span><br><span class="line">        <span class="built_in">print</span> <span class="string">&quot;* python create_csv.py /Users/xx/code/dataset ./dataset_csv.txt&quot;</span></span><br><span class="line">        sys.exit(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">elif</span> (<span class="built_in">len</span>(sys.argv) == <span class="number">3</span>):</span><br><span class="line">        SAVE_PATH = sys.argv[<span class="number">2</span>]</span><br><span class="line">    </span><br><span class="line">    BASE_PATH = sys.argv[<span class="number">1</span>]</span><br><span class="line">    SEPARATOR = <span class="string">&quot;;&quot;</span></span><br><span class="line">    fh = <span class="built_in">open</span>(SAVE_PATH,<span class="string">&#x27;w&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    label = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> dirname, dirnames, filenames <span class="keyword">in</span> os.walk(BASE_PATH):</span><br><span class="line">        <span class="keyword">for</span> subdirname <span class="keyword">in</span> dirnames:</span><br><span class="line">            subject_path = os.path.join(dirname, subdirname)</span><br><span class="line">            <span class="keyword">for</span> filename <span class="keyword">in</span> os.listdir(subject_path):</span><br><span class="line">                abs_path = <span class="string">&quot;%s/%s&quot;</span> % (subject_path, filename)</span><br><span class="line">                <span class="built_in">print</span> <span class="string">&quot;%s%s%d&quot;</span> % (abs_path, SEPARATOR, label)</span><br><span class="line">                fh.write(abs_path + SEPARATOR + <span class="built_in">str</span>(label) + <span class="string">&quot;\n&quot;</span>)</span><br><span class="line">            label = label + <span class="number">1</span></span><br><span class="line">    fh.close()</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span clas</summary>
      
    
    
    
    <category term="CS" scheme="https://blog.huihut.com/categories/CS/"/>
    
    
    <category term="Python" scheme="https://blog.huihut.com/tags/Python/"/>
    
    <category term="ML" scheme="https://blog.huihut.com/tags/ML/"/>
    
  </entry>
  
</feed>
