<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-5817647334262996203</atom:id><lastBuildDate>Mon, 07 Oct 2024 03:34:13 +0000</lastBuildDate><category>Python</category><category>C/Cpp</category><category>Linux</category><category>BCB</category><category>Skype API</category><category>Ubuntu</category><category>Win32</category><category>Lifetype</category><category>Netlimit IP Switcher</category><category>PHP</category><category>DLL</category><category>Perl</category><category>Android</category><category>Java</category><category>emomeDDSMS</category><category>wxWidgets</category><category>JSP</category><category>NDK</category><category>Debug</category><category>Eclipse</category><category>Google App Engine</category><category>JNI</category><category>SWIG</category><category>Code::Blocks</category><category>Lex</category><category>MFC</category><category>Sikuli</category><category>SudokuBoxer</category><category>Visual Studio</category><category>wxPython</category><category>xslt</category><category>程式設計</category><category>軟體</category><category>電子書</category><category>AWS</category><category>Assembly</category><category>C#</category><category>COM</category><category>CPython</category><category>CSS</category><category>Chickenfoot</category><category>Delphi</category><category>Django</category><category>FreeBSD</category><category>GDI+</category><category>Git</category><category>Jython</category><category>Lambda</category><category>MySQL</category><category>MySQL++</category><category>OCR</category><category>ORM</category><category>Round</category><category>Tesseract</category><category>Timer</category><category>TinyMCE</category><category>WinDbg</category><category>diff</category><category>libcurl</category><category>本站</category><title>Falldog的程式戰場</title><description></description><link>http://falldog7.blogspot.com/</link><managingEditor>noreply@blogger.com (Falldog)</managingEditor><generator>Blogger</generator><openSearch:totalResults>135</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-3786470942137361562</guid><pubDate>Tue, 27 Aug 2019 14:55:00 +0000</pubDate><atom:updated>2019-08-27T22:55:54.855+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">CPython</category><category domain="http://www.blogger.com/atom/ns#">Python</category><category domain="http://www.blogger.com/atom/ns#">Round</category><title>Python 2 / 3 Rounding 比較</title><description>&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;d354&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
由於 Python2.7 的末日愈來愈近了，因此敝公司最近升級 Python 至 3.6.8 (有一些考量因素，所以沒有升至3.7.x)。用熟悉的 Python 2.7 開發也有一段時間了，當初顧慮的 Performance, 以及 module 支援度都有顯著的改善。現在絕對是個很好的升級時機。&lt;/div&gt;
&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;b1ff&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
敝公司開發的系統，有一些是跟帳務系統相關的功能，所以金錢相關的 Database 欄位都是用 Decimal 處理，在從 Python2.7 升到 Python3 ，發現 rounding 的機制有些改變，在這邊分享一下我的小小研究心得。(測試以 3.6.8 為主，但是 3.7 以上的版本應該也適用)&lt;/div&gt;
&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;b1ff&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
====&amp;gt; &lt;a href=&quot;https://medium.com/@falldog/python-2-3-rounding-%E6%AF%94%E8%BC%83-e15c5faedd7e&quot; target=&quot;_blank&quot;&gt;Read More on Medium&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2019/08/python-2-3-rounding.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-2515004595312630831</guid><pubDate>Tue, 27 Aug 2019 14:55:00 +0000</pubDate><atom:updated>2019-08-27T22:55:00.310+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">AWS</category><category domain="http://www.blogger.com/atom/ns#">Lambda</category><category domain="http://www.blogger.com/atom/ns#">OCR</category><category domain="http://www.blogger.com/atom/ns#">Tesseract</category><title>在 AWS Lambda 上執行 Tesseract OCR</title><description>&lt;span style=&quot;background-color: white; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.084px;&quot;&gt;最近因為公司爬蟲需求，需要破解驗證碼，因緣際會接觸到 Tesseract ，發現是個不錯的 tool，還有 python library 可以用😍。在不做任何 Image 的 Preprocess，或是 Traing 的情況下，已經可以有五、六成的成功率(我好容易滿足啊XD)，由於爬蟲架構的需求，我們覺得 Tesseract 很適合放到 Cloud 上，當成一個 Service 執行，因此，就想在 AWS Lambda 上把它跑起來。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.084px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;1ce5&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
簡單來說，需要以下幾個流程才能把 Tesseract + pytesseract 執行起來&lt;/div&gt;
&lt;ul class=&quot;&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.8); font-family: medium-content-sans-serif-font, -apple-system, system-ui, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; list-style: none none; margin: 0px; padding: 0px;&quot;&gt;
&lt;li class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg nm nn no&quot; data-selectable-paragraph=&quot;&quot; id=&quot;988a&quot; style=&quot;box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; list-style-type: disc; margin-bottom: -0.46em; margin-left: 30px; margin-top: 2em; padding-left: 0px;&quot;&gt;Lambda Function - pytesseract&lt;/li&gt;
&lt;li class=&quot;kt ku cr ba kv b kw np ky nq la nr lc ns le nt lg nm nn no&quot; data-selectable-paragraph=&quot;&quot; id=&quot;d488&quot; style=&quot;box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; list-style-type: disc; margin-bottom: -0.46em; margin-left: 30px; margin-top: 1.05em; padding-left: 0px;&quot;&gt;Lambda Layer - Tesseract&lt;/li&gt;
&lt;li class=&quot;kt ku cr ba kv b kw np ky nq la nr lc ns le nt lg nm nn no&quot; data-selectable-paragraph=&quot;&quot; id=&quot;aab0&quot; style=&quot;box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; list-style-type: disc; margin-bottom: -0.46em; margin-left: 30px; margin-top: 1.05em; padding-left: 0px;&quot;&gt;Deploy to Lambda - by Serverless&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;5357&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
其實之前有寫過一些簡單的 Lambda (就是單純的 Python code)。但是，一想到這個新的獨立 Service，要重新設定一次所有的東西，還要自己 build 一些 module 就覺得麻煩，所以這次用了一個新的 Tool —&amp;nbsp;&lt;code class=&quot;mg mh mi mj b&quot; style=&quot;background-color: rgba(0, 0, 0, 0.05); box-sizing: inherit; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: 15.75px; padding: 2px 4px;&quot;&gt;&lt;a class=&quot;bv dh mt mu mv mw&quot; href=&quot;https://www.serverless.com/&quot; style=&quot;-webkit-tap-highlight-color: transparent; background-image: url(&amp;quot;data:image/svg+xml; background-position: 0px calc(1em + 1px); background-repeat: repeat-x; background-size: 1px 1px; box-sizing: inherit; http: //www.w3.org/2000/svg\&amp;quot;&amp;gt;&amp;lt;line x1=\&amp;quot;0\&amp;quot; y1=\&amp;quot;0\&amp;quot; x2=\&amp;quot;1\&amp;quot; y2=\&amp;quot;1\&amp;quot; stroke=\&amp;quot;rgba(0, 0, 0, 0.84)\&amp;quot; /&amp;gt;&amp;lt;/svg&amp;gt;&amp;quot;); text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;serverless framework&lt;/a&gt;&lt;/code&gt;&amp;nbsp;，輕輕鬆鬆搞定 AWS Lambda Deploy 的流程。&lt;/div&gt;
&lt;div class=&quot;kt ku cr ba kv b kw kx ky kz la lb lc ld le lf lg&quot; data-selectable-paragraph=&quot;&quot; id=&quot;5357&quot; style=&quot;background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.84); font-family: medium-content-serif-font, Georgia, Cambria, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 21px; letter-spacing: -0.004em; line-height: 1.58; margin-bottom: -0.46em; margin-top: 2em;&quot;&gt;
====&amp;gt;&amp;nbsp;&lt;a href=&quot;https://medium.com/@falldog/%E5%9C%A8-aws-lambda-%E4%B8%8A%E5%9F%B7%E8%A1%8C-tesseract-ocr-8295c28f6d13&quot; target=&quot;_blank&quot;&gt;Read More on Medium&lt;/a&gt;&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2019/08/aws-lambda-tesseract-ocr.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-6133883382085426495</guid><pubDate>Tue, 20 Jun 2017 15:38:00 +0000</pubDate><atom:updated>2017-06-20T23:44:03.272+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Django</category><category domain="http://www.blogger.com/atom/ns#">MySQL</category><category domain="http://www.blogger.com/atom/ns#">ORM</category><category domain="http://www.blogger.com/atom/ns#">Python</category><title>[Django] Query with Group_Concat (MySQL)</title><description>以下為Table &lt;b&gt;Author&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;author_id | author_name
----------+-----------
 1        | Jack
 2        | Alex
 3        | Bob
----------+-----------
&lt;/pre&gt;
&lt;br /&gt;
以下為Table &lt;b&gt;Book&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;id | author_id | book_name
---+-----------+----------
 1 | 1         | Hello
 2 | 1         | World
 3 | 1         | Wolf
 4 | 2         | Sex
---+-----------+----------
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
MySQL&lt;/h2&gt;
&lt;h4&gt;
Case1 (簡單的case)&lt;/h4&gt;
希望將Book by Author Group 起來，然後將 book_name 全部 string concat 起來後，期望得到的結果如下：&lt;br /&gt;
&lt;b&gt;&lt;i&gt;author_id=1, book_name=Hello,World,Wolf&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;author_id=2, book_name=Sex&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
在MySQL中，提供了Aggregate Function: &lt;b&gt;GROUP_CONCAT&lt;/b&gt;() 可以輕鬆做到這個功能&lt;br /&gt;
&lt;div&gt;
&lt;b&gt;&lt;i&gt;SQL Command&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;SELECT author_id, GROUP_CONCAT(book_name)
FROM Book
GROUP BY author_id&lt;/pre&gt;
&lt;h4&gt;
Case2 (較複雜的case, table join)&lt;/h4&gt;
今天假設希望知道 Author的 Name 加上所有的 book_name String Concat 的結果&lt;br /&gt;
&lt;b&gt;&lt;i&gt;author_name=Jack, book_name=Hello,World,Wolf&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;author_name=Alex, book_name=Sex&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;SQL Command&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;SELECT A.author_name, GROUP_CONCAT(B.book_name) AS book_name
FROM Author A
JOIN Book B ON A.author_id = B.author_id
GROUP BY B.author_id
&lt;/pre&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;
Django&lt;/h2&gt;
上面所提到的，都是MySQL的方法，那在Django中要如何透過Django的ORM做到這個功能呢? 就要靠Django的Aggregate class 來處理。&lt;br /&gt;
&lt;br /&gt;
首先，要先繼承Aggregate，將MySQL的 Function包裝成Aggregate Wrapper&lt;br /&gt;
如果看 Django source code (django.db.models.aggregates.py)&lt;br /&gt;
可以發現常用來aggregate的 Sum, Count, Avg, Max, Min 都是用這種作法做的&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;from django.db.models import Aggregate, CharField

class GroupConcat(Aggregate):
    # GROUP_CONCAT(DISTINCT field_name SEPARATOR &#39;, &#39;)
    function = &#39;GROUP_CONCAT&#39;
    template = &quot;%(function)s(%(distinct)s %(expressions)s %(separator)s)&quot;

    def __init__(self, expression, distinct=False, separator=&#39;, &#39;, **extra):
        super(GroupConcat, self).__init__(
            expression,
            distinct=&#39;DISTINCT&#39; if distinct else &#39;&#39;,
            separator=&quot;SEPARATOR &#39;%s&#39;&quot; % separator,
            output_field=CharField(),
            **extra
        )
&lt;/pre&gt;
&lt;br /&gt;
接下來就可以用Django的ORM的乾淨語法得到我們要的結果了&lt;br /&gt;
GroupConcat的 separator指定為 &lt;b&gt;&#39;, &#39;&lt;/b&gt; (含空格) 可以依需求修改&lt;br /&gt;
其實還可以指定Order By，如果有需求的話再根據MySQL的文件修改GroupConcat的template&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;class Author(models.Model):
    author_id = models.AutoField(primary_key=True)
    author_name = models.CharField(max_length=32)

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(Author, relate_name=&quot;books&quot;)
    book_name = models.CharField(max_length=32)

query = Author.objects.annotate(book_name=GroupConcat(&#39;books__book_name&#39;))
for author in query:
    print(&quot;author_name=%s book_name=%s&quot; % (author.author_name, author.book_name))
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Reference:&lt;/b&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat&quot; target=&quot;_blank&quot;&gt;MySQL - GROUP_CONCAT()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.djangoproject.com/en/1.11/ref/models/expressions/#creating-your-own-aggregate-functions&quot; target=&quot;_blank&quot;&gt;Django 1.11 - Create your own Aggregate Function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2017/06/django-query-with-groupconcat-mysql.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-1170585110768504103</guid><pubDate>Wed, 14 Jan 2015 09:59:00 +0000</pubDate><atom:updated>2015-01-15T11:22:38.812+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><category domain="http://www.blogger.com/atom/ns#">WinDbg</category><title>[WinDbg] Remote Kernel Debug over Network cable</title><description>WinDbg 不僅可以用來 Debug User mode 的 process，還可以用來 Debug Kernel mode 的 Windows，基本上使用的方式必須有兩台電腦，或是 VM ，因為 你如果要做 local 的 Kernel Debug 的話，中斷點 hit 到的話，整台電腦應該就會 block 住，但是 local Kernel Debug 無法這麼做的。&lt;br /&gt;
&lt;br /&gt;
既然要透過 remote 的方式來做 Kernel Debug，所以 Windows 提供了不少方法讓你連線到另一台電腦，包括 &lt;b&gt;Serial cable (COM)&lt;/b&gt;、&lt;b&gt;1394 cable&lt;/b&gt;、&lt;b&gt;Network cable&lt;/b&gt;、&lt;b&gt;USB cable&lt;/b&gt; …等等，其中 Serial cable &amp;amp; 1394 使用上的限制比較少，support 的平台也比較多，Network cable 與 USB cable 對硬體與平台的限制都不少，所以要確認你的硬體平台有支援的話，才可以透過 Network cable, USB cable 來做 debug。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
這次就來介紹一下：透過 Network cable 來做 Kernel Debug，限制如下&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Target computer - Windows 8.0+&lt;/li&gt;
&lt;li&gt;Target computer - &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/dn337010(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;網卡 Vendor 支援清單&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Host computer - Windows XP+&lt;/li&gt;
&lt;li&gt;Host computer - WinDbg version 要 &lt;a href=&quot;http://msdn.microsoft.com/en-us/windows/hardware/hh852365&quot; target=&quot;_blank&quot;&gt;WDK 8.1+&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
1. 確認 Target computer 網卡支援性&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
啟動裝置管理員 Device Manager (或是執行指令 devmgmt.msc)&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidWOvg2LhRZFtpR40QNvxUTvZ3ppLWoGbjdSLwdGHAipQBQJcOp_Mww1RFBbd-Fi6_iwOWCCxozDe5mvDbXEbIvD2VvkDAybBXWeoGNRgB2z1a7N9R337T0NV8myzSuFVigYvhoVv5EXZm/s1600/devmgmt.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidWOvg2LhRZFtpR40QNvxUTvZ3ppLWoGbjdSLwdGHAipQBQJcOp_Mww1RFBbd-Fi6_iwOWCCxozDe5mvDbXEbIvD2VvkDAybBXWeoGNRgB2z1a7N9R337T0NV8myzSuFVigYvhoVv5EXZm/s1600/devmgmt.png&quot; height=&quot;320&quot; width=&quot;272&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
Device Manager&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
找到你的網卡，點右鍵，選Property&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkJKv1G5rSZzSXSuN5Ngpq8m60NJ9AAveEJ7oRRGDyBETM-3S-fEOM6OvrawSK6A8CfeZmVt2UnP0hgPBMPd9qafWQd_618jJchvdMRKuPiSlei0qS8TzZDtMB77uVagBcE_L3W9Deo1fC/s1600/ethernet_property2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkJKv1G5rSZzSXSuN5Ngpq8m60NJ9AAveEJ7oRRGDyBETM-3S-fEOM6OvrawSK6A8CfeZmVt2UnP0hgPBMPd9qafWQd_618jJchvdMRKuPiSlei0qS8TzZDtMB77uVagBcE_L3W9Deo1fC/s1600/ethernet_property2.png&quot; height=&quot;320&quot; width=&quot;276&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
Ethernet Properties&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
注意看Value：PCI\VEN_8086&amp;amp;DEV_155A&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;Vendor ID = 8086&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;Device ID = 155A&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
照著這個 Vendor ID &amp;amp; Device ID 到 &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/dn337010(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;MSDN 網頁&lt;/a&gt;中比對一下，如果找得到的話，恭喜你，代表這台電腦是可以做 Kernel Debug的。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV3NTEXVEHLr6CA-xedJ9OXZufi4CUzwc_CCqemaPZQaO883FONUkseFousi8pOZIKjUMvht1QXU3AG3nXFZb8wmJyuAw057K-uEGphZ5cLocxA1ONuXCMlpLpIrH3SXtow1S7uOpmBgMS/s1600/ethernet_property1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV3NTEXVEHLr6CA-xedJ9OXZufi4CUzwc_CCqemaPZQaO883FONUkseFousi8pOZIKjUMvht1QXU3AG3nXFZb8wmJyuAw057K-uEGphZ5cLocxA1ONuXCMlpLpIrH3SXtow1S7uOpmBgMS/s1600/ethernet_property1.png&quot; height=&quot;320&quot; width=&quot;276&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
圖3 (Optional)&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
Ethernet Properties&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
當你的電腦不止一張網卡的話&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
要注意圖中的 Location ： PCI bus &lt;b&gt;&lt;span style=&quot;color: #990000;&quot;&gt;0&lt;/span&gt;&lt;/b&gt;, device &lt;b&gt;&lt;span style=&quot;color: #990000;&quot;&gt;25&lt;/span&gt;&lt;/b&gt;, function &lt;b&gt;&lt;span style=&quot;color: #990000;&quot;&gt;0&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
這個 magic number 在之後會用到&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
2. 開啟 Target computer 的 Debug mode&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
在舊 XP 的時代，開啟 Debug mode 必須透過 boot.ini，但是在 Vista 以後，可以透過 &lt;b&gt;bcdedit &lt;/b&gt;指令直接開啟 Debug 的功能&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
以 &lt;b&gt;&lt;span style=&quot;color: #990000;&quot;&gt;admin &lt;/span&gt;&lt;/b&gt;的權限開啟 cmd (命令提示字元)&lt;br /&gt;
確認你的 host computer 的 ip(w.x.y.z) &amp;amp; port(n 建議50000+)&lt;br /&gt;
兩台電腦必須在同一個網域或是 ping 得到對方的 ip 才行&lt;/div&gt;
&lt;div&gt;
輸入以下指令&lt;/div&gt;
&lt;pre class=&quot;cmd&quot;&gt;bcdedit /debug on
bcdedit /dbgsettings net hostip:w.x.y.z port:n&lt;/pre&gt;
&lt;div&gt;
bcdedit 會回傳一組 Key，必須將這組 Key 傳至 host computer&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
如果你有超過一張網卡以上&lt;br /&gt;
必須再設定你連線的網卡是哪一張&lt;br /&gt;
指定 busparams b.d.f (參考 圖3 取得 bus id, device id, function id)&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;bcdedit /set &quot;{dbgsettings}&quot; busparams b.d.f&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
最後可以確認一下你目前的設定是什麼&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;bcdedit /dbgsettings&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
3. Host computer 開始 debug&lt;/h3&gt;
接上網路線&lt;br /&gt;
在 Host computer 開啟 WinDbg，選擇&lt;span style=&quot;background-color: #f6b26b;&quot;&gt; File | Kernel Debug&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNcpeDci5oseBH32F0WeNFQQLfTEO4OUf1aqqJanUjmjETf-mFstzRXoKKKwnkJ1PXOLUPAez7PurYn-KAKVLdVFwvBA38OmUblX9FLZsvtb2D2mzgTpT7MRq4i_Y37EtkxllN9fDctmv/s1600/windbg_net.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNcpeDci5oseBH32F0WeNFQQLfTEO4OUf1aqqJanUjmjETf-mFstzRXoKKKwnkJ1PXOLUPAez7PurYn-KAKVLdVFwvBA38OmUblX9FLZsvtb2D2mzgTpT7MRq4i_Y37EtkxllN9fDctmv/s1600/windbg_net.png&quot; height=&quot;213&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
輸入正確的 port 與 Key&lt;/div&gt;
按下確定後&lt;br /&gt;
Target computer 重開機應該就可以開始 debug 了&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
指令&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Ctrl + Break &lt;span style=&quot;color: #38761d;&quot;&gt;(馬上中斷)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Ctrl + Alt + K &lt;span style=&quot;color: #38761d;&quot;&gt;(Target computer 重開機時，在 Windows initialize 後馬上中斷)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;ed Kd_DEFAULT_Mask 0x8 &lt;span style=&quot;color: #38761d;&quot;&gt;&amp;nbsp;# display default kernel log&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;dd Kd_DEFAULT_Mask &amp;nbsp;&lt;span style=&quot;color: #38761d;&quot;&gt;# disable display default kernel log&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Reference&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/hh439346(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;MSDN - Setting up Kernel Mode Debugging over a Network cable manually&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/dn337010(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;MSDN - Supported Ethernet NICs for Network Kernel Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/hardware/ff542187(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;BCDEdit - dbgsettings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://briolidz.wordpress.com/2013/11/17/windbg-some-debugging-commands/&quot; target=&quot;_blank&quot;&gt;Some WinDbg commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2015/01/windbg-remote-kernel-debug-over-network.html</link><author>noreply@blogger.com (Falldog)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidWOvg2LhRZFtpR40QNvxUTvZ3ppLWoGbjdSLwdGHAipQBQJcOp_Mww1RFBbd-Fi6_iwOWCCxozDe5mvDbXEbIvD2VvkDAybBXWeoGNRgB2z1a7N9R337T0NV8myzSuFVigYvhoVv5EXZm/s72-c/devmgmt.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-1276568209668281841</guid><pubDate>Tue, 13 Jan 2015 05:39:00 +0000</pubDate><atom:updated>2015-01-14T18:01:50.795+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">DLL</category><title>[C#] Allocate structure buffer array from DLL</title><description>C# 透過 DllImport 的方式讓你可以直接使用 C/C++ DLL 的 function，C/C++ 的程式常使用 struct 來儲存 data ，C# 也提供了讓你在 C# 中 define struct layout，這個轉換方式可以在 C# 中，直接宣告一個 struct 變數，丟入 DLL 中使用。&lt;br /&gt;
&lt;br /&gt;
這點跟 Python 其實滿像的，Python 有 ctypes 可以做到類似的行為。script 中的 memory 跟 C/C++ 的 memory 無法互通，都必須透過轉換的方式讓 interpreter 可以順利看得懂 memory buffer。&lt;br /&gt;
&lt;br /&gt;
C# 單一個 struct buffer 使用上都沒什麼問題，但是當你試著想要從 DLL 中撈回一串 struct array buffer時，就無法用直覺的方法完成這件事。因為 C# 在 DllImport 時的參數傳遞動了點手腳，所以如果直接將 C# 的 struct array 加 ref &amp;nbsp;傳至 DLL 可能會導致 crash 的產生。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
1. 測試 C# dump struct buffer&lt;/h3&gt;
測試一下 C# 在傳遞 struct buffer 的行為，將傳入的 struct address print 出來看看&lt;br /&gt;
printf() 可以替換為 OutputDebugString() 至 DbgView 中看結果會比較方便&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;TestDLL.cpp&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#define DLL_API __declspec(dllexport)

typedef struct _Data
{
 bool bData;
 int nData;
 char strData[256];
} Data;

#ifdef __cplusplus
extern &quot;C&quot; {
#endif
 DLL_API bool Test_DumpAddress(Data* p)
 {
  printf(&quot;Test_DumpAddress() address=0x%p\n&quot;, p);
  return true;
 }

 DLL_API bool Test_DumpData(Data* d)
 {
  printf(&quot;Test_DumpData() address=0x%p bool=%d, int=%d, str=%s\n&quot;, d, d-&amp;gt;bData, d-&amp;gt;nData, d-&amp;gt;strData);
  return true;
 }
#ifdef __cplusplus
}
#endif
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;TestDLL.cs&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;class Program
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Data
    {
        public bool bData;
        public int nData;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string strData;
    }

    [DllImport(&quot;TestDLL.dll&quot;, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Test_DumpAddress(ref Data p);

    [DllImport(&quot;TestDLL.dll&quot;, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern bool Test_DumpData(ref Data d);

    static void Main(string[] args)
    {
        // testing for dump single struct buffer
        Data sd = new Data();
        sd.bData = false;
        sd.nData = 99;
        sd.strData = &quot;Falldog&quot;;
        Test_DumpData(ref sd);
        Test_DumpAddress(ref sd);

        // testing for dump struct buffer array
        Data[] sd_array = new Data[5];
        for (int i = 0; i &amp;lt; 5; i++ )
        {
            sd_array[i].bData = false;
            sd_array[i].nData = 100+i;
            sd_array[i].strData = &quot;Falldog&quot;;
            Test_DumpData(ref sd_array[i]);
        }

        Console.ReadLine();  // enter to end the process
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Result : &lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;[4660] Test_DumpData() address=0x0035EB74 bool=0, int=99, str=Falldog
[4660] Test_DumpAddress() address=0x0035EB74
[4660] Test_DumpData() address=0x0035EB74 bool=0, int=100, str=Falldog
[4660] Test_DumpData() address=0x0035EB74 bool=0, int=101, str=Falldog
[4660] Test_DumpData() address=0x0035EB74 bool=0, int=102, str=Falldog
[4660] Test_DumpData() address=0x0035EB74 bool=0, int=103, str=Falldog
[4660] Test_DumpData() address=0x0035EB74 bool=0, int=104, str=Falldog
&lt;/pre&gt;
&lt;br /&gt;
明顯看到 address 都是一樣的！在 C# 中明明是不一樣的變數，在傳入 DLL 後，address 都變一樣了，應該就是 C# 中間會產生一個 temp 的 buffer 來做轉換。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
2. 將 DLL allocate 的 buffer load 至 C# 的 struct memory 中&lt;/h3&gt;
以下為 C# 透過 DLL allocate 一塊 buffer，讓 DLL 填完後，在 C# 轉換為 C# 看得懂的 struct array buffer，所以傳下去的 buffer pointer type 為 IntPtr ，取出來後 再用 Marshal.PtrToStructure() 將 buffer 轉為 struct buffer，最後記得要將 DLL allocate 出來的 buffer free 掉，否則會 memory leak。&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;TestDLL.cpp&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#define DLL_API __declspec(dllexport)

typedef struct _Data
{
 bool bData;
 int nData;
 char strData[256];
} Data;

#ifdef __cplusplus
extern &quot;C&quot; {
#endif
 DLL_API void Test_AllocData(int count, Data*&amp;amp; res)
 {
  res = new Data[count];
  for(int i=0 ; i&amp;lt;count ; i++){
   res[i].bData = true;
   res[i].nData = 500 + i;
   sprintf_s(res[i].strData, &quot;Test_AllocData(%d)&quot;, i);
  }
 }

 DLL_API void Test_FreeData(Data* d)
 {
  if(d)
   delete [] d;
 }

#ifdef __cplusplus
}
#endif
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;TestDLL.cs&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;class Program
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Data
    {
        public bool bData;
        public int nData;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string strData;
    }

    [DllImport(&quot;TestDLL.dll&quot;, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Test_AllocData(int size, ref IntPtr ptr);

    [DllImport(&quot;TestDLL.dll&quot;, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Test_FreeData(IntPtr ptr);

    static void Main(string[] args)
    {
        // testing for retrive struct array buffer from DLL
        IntPtr binary = new IntPtr();
        {
            Data[] ad = new Data[3];
            Test_AllocData(3, ref binary);
            ad[0] = (Data)Marshal.PtrToStructure(binary + Marshal.SizeOf(typeof(Data)) * 0, typeof(Data));
            ad[1] = (Data)Marshal.PtrToStructure(binary + Marshal.SizeOf(typeof(Data)) * 1, typeof(Data));
            ad[2] = (Data)Marshal.PtrToStructure(binary + Marshal.SizeOf(typeof(Data)) * 2, typeof(Data));
            Test_FreeData(binary);

            for (int i = 0; i &amp;lt; 3; i++)
            {
                Console.WriteLine(string.Format(&quot;@AllocData from DLL i={0} n={1} str={2}&quot;, i, ad[i].nData, ad[i].strData));
            }
        }
        Console.ReadLine();  // enter to end the process
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
C# 的 DLL import 還有不少有趣的東西，只是因為接觸不多，沒時間好好來研究&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx&quot; target=&quot;_blank&quot;&gt;MSDN - Using the DllImport Attribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mono-project.com/docs/advanced/pinvoke/&quot; target=&quot;_blank&quot;&gt;Mono - Interop with Native Libraries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2015/01/c-sharp-allocate-structure-buffer-array-dll.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-3887025523915157289</guid><pubDate>Wed, 03 Sep 2014 12:41:00 +0000</pubDate><atom:updated>2014-09-03T20:43:31.766+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">diff</category><category domain="http://www.blogger.com/atom/ns#">Git</category><category domain="http://www.blogger.com/atom/ns#">Ubuntu</category><title>[Ubuntu] Git difftool - Meld</title><description>Meld 是個跨平台的 GUI diff &amp;amp; merge tool，重點是，還是免費的呢！&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://meldmerge.org/images/meld-mary.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://meldmerge.org/images/meld-mary.png&quot; height=&quot;148&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
以下簡介一下在 Ubuntu 上如何安裝設定 Meld&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
安裝&lt;/h3&gt;
&lt;pre class=&quot;cmd&quot;&gt;sudo apt-get update
sudo apt-get install meld
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
設定 git default diff tool 為 meld&lt;/h3&gt;
&lt;pre class=&quot;cmd&quot;&gt;git config --global diff.tool meld
git config --global --add difftool.prompt false
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
使用範例&lt;/h3&gt;
&lt;pre class=&quot;cmd&quot;&gt;cd &amp;lt;git repo dir&amp;gt;
git difftool           // display file diff one by one
git difftool file_path // display one file diff
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://meldmerge.org/&quot; target=&quot;_blank&quot;&gt;Meld&lt;/a&gt; - official site&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2014/09/ubuntu-git-difftool-meld.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-3078770235859958332</guid><pubDate>Fri, 27 Dec 2013 10:46:00 +0000</pubDate><atom:updated>2014-09-13T12:00:23.835+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JNI</category><category domain="http://www.blogger.com/atom/ns#">NDK</category><category domain="http://www.blogger.com/atom/ns#">SWIG</category><title>[Java] 透過SWIG 從JNI (C/C++) callback 回 Java</title><description>最近寫 Android，一般 Java 層可以透過 JNI 呼叫 C/C++ 撰寫的 .so 檔，但是要從 C/C++ 呼叫回 Java 層呢!? 一般需要 JNIEnv 這個特殊的變數，才可以透過它來呼叫到 Java Library。&lt;br /&gt;
&lt;br /&gt;
不過今天這邊要介紹的是另外一個方法 - 透過 SWIG 的 directors 的 feature&lt;br /&gt;
SWIG 可以將 C++ 的 class 包裝成一個 Java layer 的 class ，而 Java layer 可以去繼承 Java wrap C++ 的 class，然後 override 它的 virtual function 後，C/C++ layer 呼叫到這個 virtual function 時，就會被轉 call 到 Java layer了。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
以下是簡單的 sample code&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MyLib.h&lt;/b&gt;&lt;br /&gt;
在 Callback function 前加上 &lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;virtual&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#ifndef __MY_LIB_H
#define __MY_LIB_H
class Base
{
public:
     Base(){}
     virtual ~Base(){}
     void CallIn(int num1, int num2);
     virtual void Callback(int num1, int num2); //setting in virtual for override
};
#endif
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MyLib.cpp&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#include &quot;MyLib.h&quot;
#include &amp;lt;android/log.h&amp;gt;
void Base::CallIn(int num1, int num2)
{
    Callback(num1+1, num2+1); // add the number 
}
void Base::Callback(int num1, int num2)
{
    // If override this function in Java layer, you will not see the log
    __android_log_print(ANDROID_LOG_DEBUG, 
                        &quot;MyLib&quot;, 
                        &quot;Base::Callback() num1=%d, num2=%d&quot;, num1, num2);
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;MyLib.i&lt;/b&gt;&lt;br /&gt;
在 .i 檔中，加上&lt;b&gt; %feature(&quot;&lt;span style=&quot;color: #cc0000;&quot;&gt;director&lt;/span&gt;&quot;)&lt;/b&gt; 後面加上 想處理的 class name&lt;br /&gt;
這樣 SWIG 就會自動處理 class name 底下所有的 virtual function&lt;br /&gt;
若不指定的話，SWIG 會處理所有的 class 的 virtual function&lt;br /&gt;
也可以加上 &lt;b&gt;%feature(&quot;&lt;span style=&quot;color: #cc0000;&quot;&gt;nodirector&lt;/span&gt;&quot;) Foo::Bar;&lt;/b&gt; 將 disable 指定的 virtual function&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;%module(directors=&quot;1&quot;) MyLib
%{
  #include &quot;MyLib.h&quot;
%}

%feature(&quot;director&quot;) Base;
%include &quot;MyLib.h&quot;

%pragma(java) jniclasscode=%{
    static {
        try {
            java.lang.System.loadLibrary(&quot;MyLib&quot;);
        } catch (UnsatisfiedLinkError e) {
            java.lang.System.err.println(&quot;JNI error: &quot; + e);
            java.lang.System.exit(1);
        }
    }
%}&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Android.mk&lt;/b&gt;&lt;br /&gt;
務必要加上&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;-fexceptions -frtti&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;，這樣 SWIG 才有能力處理 class override&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := MyLib
LOCAL_SRC_FILES := MyLib_wrap.cpp MyLib.cpp
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := -fexceptions -frtti #for SWIG director feature
include $(BUILD_SHARED_LIBRARY)
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;MainActivity.java&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;import com.yourapp.Base
//... other import

public class MainActivity extends Activity
{
    class JDerived extends Base
    {
        @Override
        public void Callback(int num1, int num2)
        {
            String msg = String.format(
                             &quot;Derived::Callback() num1=%d, num2=%d&quot;,
                             num1, num2 );
            System.out.println(msg);
        }
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        JDerived d = new JDerived();
        d.CallIn(1,2);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
最後輸出的 output 結果就是&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;&amp;gt;&amp;gt;&amp;gt; Derived::Callback() num1=2, num2=3
&lt;/pre&gt;
&lt;br /&gt;
最後，由於 SWIG 在處理 virtual function 時，需要多 wrapper 好幾層的 function，因而增加了一些 function call 的 overhead，所以盡量指定想被 override 的 virtual function 即可。&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;SWIG - &lt;a href=&quot;http://www.swig.org/Doc2.0/Java.html#Java_directors&quot; target=&quot;_blank&quot;&gt;Java # Cross language polymorphism using directors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.swig.org/Doc2.0/Android.html&quot; target=&quot;_blank&quot;&gt;SWIG and Android&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/12/java-swig-jni-cc-callback-java.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-5689627911943958539</guid><pubDate>Fri, 20 Dec 2013 02:46:00 +0000</pubDate><atom:updated>2013-12-20T10:46:48.708+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">emomeDDSMS</category><title>[emomeDDSMS] 下載emome上的備份簡訊 更新0.74</title><description>emome更新&lt;div&gt;
好久沒更新了，最近要備份才發現網頁更新了 XD，就順手改了一下&lt;/div&gt;
&lt;div&gt;
還得要抓到舊版的 Firefox 3.6 才行，還好 chickenfoot 的連結還在...&lt;br /&gt;下載連結(按右鍵另存新檔)：&lt;a href=&quot;http://dl.dropbox.com/u/17213022/emomeDDSMS/emomeDDSMS.0.74.js&quot; target=&quot;_blank&quot;&gt;emomeDDSMS 0.74&lt;/a&gt; (2013/12/20)&lt;br /&gt;
&lt;br /&gt;
使用說明，請參考&lt;a href=&quot;http://falldog7.blogspot.tw/2009/08/emomeddsms-emome.html&quot; target=&quot;_blank&quot;&gt;前一篇&lt;/a&gt;文章。&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2013/12/emomeddsms-emome-074.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-7560654319484259379</guid><pubDate>Wed, 11 Dec 2013 06:44:00 +0000</pubDate><atom:updated>2014-09-13T12:00:38.787+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JNI</category><category domain="http://www.blogger.com/atom/ns#">NDK</category><category domain="http://www.blogger.com/atom/ns#">SWIG</category><title>[JNI] 在C/C++中透過 SWIG 取得 JNIEnv or JavaVM</title><description>在 C/C++ layer 裡，想要 call Java layer 的 function 的話，適必需要 JNIEnv or JavaVM 這兩個 instance pointer，而透過 SWIG 包裝起來的 C/C++ layer 是不能直接接觸到 JNI layer，必須要一些手法才行。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
在 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;.i &lt;/span&gt;&lt;/b&gt;檔，偷埋一些 function&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;MyNDK.i&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;%module MyNDK
%{
    #include &quot;MyNDK.h&quot;
}%

%include &quot;MyNDK.h&quot;

%init %{
    JavaVM* g_cached_jvm = NULL;
    JNIEnv* g_cached_env = NULL;
    
    jint JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        g_cached_jvm = vm;
        if (vm-&amp;gt;GetEnv((void**)&amp;amp;g_cached_env, JNI_VERSION_1_6) != JNI_OK) {
            return -1;
        }
        return JNI_VERSION_1_6;
    }

    JavaVM* JNI_GetVM()
    {
        return g_cached_jvm;
    }
    
    JNIEnv* JNI_GetEnv()
    {
        return g_cached_env;
    }
%}&lt;/pre&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;MyNDK.h&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#ifndef __MY_NDK_H__
#define __MY_NDK_H__
#include &amp;lt;jni.h&amp;gt;
const char* GetLocalStorageDir(jobject activity);
#endif //__MY_NDK_H__
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
在 .cpp 檔裡，透過剛偷埋的 function ，就能拿到 JNIEnv or JavaVM 了&lt;br /&gt;
&lt;h4&gt;
&lt;b&gt;MyNDK.cpp&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#include &quot;MyNDK.h&quot;
#include &amp;lt;string&amp;gt;

extern JNIEnv* JNI_GetEnv();
std::string gCachedLocalStorageDir;

const char* GetLocalStorageDir(jobject activity)
{
    JNIEnv* env = JNI_GetEnv();
    jclass clsContext = env-&amp;gt;FindClass(&quot;android/content/Context&quot;);
    jclass clsFile = env-&amp;gt;FindClass(&quot;java/io/File&quot;);
    jmethodID midGetFilesDir = env-&amp;gt;GetMethodID(clsContext, &quot;getFilesDir&quot;,&quot;()Ljava/io/File;&quot;);
    jmethodID midGetPath = env-&amp;gt;GetMethodID(clsFile, &quot;getPath&quot;,&quot;()Ljava/lang/String;&quot;);
    jobject objFile = env-&amp;gt;CallObjectMethod(activity, midGetFilesDir);
    jstring objPath = (jstring) env-&amp;gt;CallObjectMethod(objFile, midGetPath);
    const char* path = env-&amp;gt;GetStringUTFChars(objPath, NULL);
    gCachedLocalStorageDir = path;
    env-&amp;gt;ReleaseStringUTFChars(objPath, path);
    return gCachedLocalStorageDir.c_str();
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
記住，如果是在 C/C++ layer create 的 pthread 裡，想呼叫 JNI 的 code，一定要 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;AttachCurrentThread&lt;/span&gt;&lt;/b&gt;，否則，可能會造成 AP crash！因為 JNIEnv* 只能在同一條 thread 取得與使用。不要試著拿 global 的 JNIEnv* 變數，因為可能是別條 thread 所 created 的，像上面的例子，就是 JNI_OnLoad() 時，拿到的 JNIEnv* ，不能給其他條 thread 所用。&lt;br /&gt;
&lt;h4&gt;
AttachCurrentThread sample code :&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;bool ProcessJNISafe()
{
    bool isDoAttach = false;
    JavaVM* jvm = JNI_GetVM();
    JNIEnv* env = NULL;
    
    // Get JNIEnv &amp;amp; try Attach
    jint ret = jvm-&amp;gt;GetEnv((void **)&amp;amp;env, JNI_VERSION_1_6);
    if( ret == JNI_EDETACHED ) {
        if( jvm-&amp;gt;AttachCurrentThread(&amp;amp;env, NULL) &amp;lt; 0 )
            return false;
        isDoAttach = true;
    }
    else if( ret != JNI_OK ) {
        return false;
    }
    
    // process JNI layer here
    {
    }
    
    // Detach
    if(isDoAttach)
    {
        jvm-&amp;gt;DetachCurrentThread();
    }
    return true;
}&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Reference:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Android - &lt;a href=&quot;http://developer.android.com/training/articles/perf-jni.html&quot; target=&quot;_blank&quot;&gt;JNI Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SWIG - &lt;a href=&quot;http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn44&quot; target=&quot;_blank&quot;&gt;Initialization blocks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;</description><link>http://falldog7.blogspot.com/2013/12/jni-cc-swig-jnienv-or-javavm.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-8387800668558567370</guid><pubDate>Wed, 11 Dec 2013 05:08:00 +0000</pubDate><atom:updated>2014-09-13T12:00:47.477+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">libcurl</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><title>[C/C++] 在 Windows 上 Build static libCURL library</title><description>&lt;a href=&quot;http://curl.haxx.se/&quot; target=&quot;_blank&quot;&gt;libcurl &lt;/a&gt;是個跨平台的 library ，支援非常多的 protocol，重點還是 open source!&lt;br /&gt;
以下就是簡單的 build 出一個 libcurl 的 static library 教學&lt;br /&gt;
&lt;h2&gt;
1. 首先 download libcurl 的 source code 壓縮檔&lt;/h2&gt;
&lt;a href=&quot;http://curl.haxx.se/download.html&quot; target=&quot;_blank&quot;&gt;libCURL download page&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
2. 在 command line 準備好 VC 的 compile 環境&lt;/h2&gt;
&lt;pre class=&quot;cmd&quot;&gt;&quot;{VC Install Path}\VC\vcvarsall.bat&quot; x86&lt;/pre&gt;
設置完環境後，才能執行 namke&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
3. 開始 build libcurl&lt;/h2&gt;
&lt;pre class=&quot;cmd&quot;&gt;cd {libcurl extract dir}\winbuild
nmake /f Makefile.vc mode=static DEBUG=yes MAXHINE=x86&lt;/pre&gt;
mode = static 也可以是 dll ，只是我們目標是 static library&lt;br /&gt;
build 完後，可以在 &lt;i&gt;&lt;b&gt;{libcurl extract dir}\builds &lt;/b&gt;&lt;/i&gt;找到 lib 還有 header 檔&lt;br /&gt;
&lt;br /&gt;
其他參數說明&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;VC=&amp;lt;6,7,8,9,10&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;VC版本(不一定要填)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;span style=&quot;color: #660000;&quot;&gt;&lt;b&gt;WITH_SSL&lt;/b&gt;&lt;b&gt;=&amp;lt;dll or static&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;使用OpenSSL詳細&lt;a href=&quot;http://swatrant.blogspot.tw/2013/06/how-to-build-curl-static-library-with.html&quot; target=&quot;_blank&quot;&gt;參閱&lt;/a&gt;，會有 License 問題&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;ENABLE_WINSSL=&amp;lt;yes or no&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Enable native 的 Windows SSL 功能&lt;/li&gt;
&lt;li&gt;記得，如果要 enable 的話，ENABLE_SSPI一定也要 enable !&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;GEN_PDB=&amp;lt;yes or no&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;產生 .pdb 檔&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;DEBUG=&amp;lt;yes or no&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Debug or Release mode&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;MACHINE=&amp;lt;x86 or x64&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Target architecture&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #660000;&quot;&gt;RTLIBCFG&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;不指定就是 default，compile 參數會加上 /MD or /MDd (Multi-threaded)&lt;/li&gt;
&lt;li&gt;=static，compile 參數會加上&amp;nbsp;/MT or /MTd (Multi-threaded DLL)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;h2&gt;
4. VC project setting 設置&lt;/h2&gt;
在&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; Project Property | Linker | General | Additional Library Directories&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
加上放有 build 出的 .lib 的目錄&lt;br /&gt;
&lt;br /&gt;
在&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; Project Property | Linker | Input | Additional Dependencies&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
加上 libcurl_a.lib or libcurl_a_debug.lib&lt;br /&gt;
&lt;br /&gt;
在&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; Project Property | C/C++ | Preprocessor&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
加上 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;CURL_STATICLIB&lt;/span&gt;&lt;/b&gt; 這個 macro 才行&lt;br /&gt;
否則會出現類似這樣的錯誤訊息：&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_global_init referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_append referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_free_all referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_strerror referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_init referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_setopt referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_perform referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
1&amp;gt;A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_cleanup referenced in function &quot;bool __cdecl DownloadProtectedKey(class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt; &amp;amp;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;,class std::basic_string&amp;lt;char,struct std::char_traits&amp;lt;char&amp;gt;,class std::allocator&amp;lt;char&amp;gt; &amp;gt;)&quot; (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://falldog7.blogspot.com/2013/12/cc-windows-build-static-libcurl-library.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-4607752801943210044</guid><pubDate>Tue, 12 Nov 2013 09:57:00 +0000</pubDate><atom:updated>2015-01-14T18:02:10.011+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">DLL</category><category domain="http://www.blogger.com/atom/ns#">Linux</category><title>[Linux/Android] Export API for SharedLibrary (.so)</title><description>當開發一個 SharedLibrary (.so) 時，不想 Export 太多 API 出去(可能涉及商業機密或是單純的爽字)，Windows or Linux 都有做法可以做到，這邊只說明一下 Linux / Android 的做法。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
用 nm 觀察 .so 的 Symbol Table&lt;/h3&gt;
&lt;pre class=&quot;cmd&quot;&gt;nm -gC MyLib.so&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;-g : 只列出 external symbol&lt;/li&gt;
&lt;li&gt;-C : 將 C++ 的 symbol 轉換成易讀的版本&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Android NDK 在 toolchain 的 prebuild 資料夾裡，也有 ARM/x86 的 &lt;b&gt;&lt;span style=&quot;color: #134f5c;&quot;&gt;nm.exe &lt;/span&gt;&lt;/b&gt;可以使用&lt;br /&gt;
&lt;br /&gt;
比如，在我的 Windows x64 NDK 底下&lt;br /&gt;
&lt;i&gt;&lt;b&gt;%NDK_PATH%&lt;/b&gt;/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/arm-linux-androideabi/bin/nm.exe&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
記得，不同的 ABI Type，要用相對應的 folder 底下的 nm.exe 才行。&lt;br /&gt;
&lt;br /&gt;
在 GCC or G++ 的參數加上&lt;span style=&quot;color: #cc0000;&quot;&gt; &lt;b&gt;-fvisiblity=hidden&lt;/b&gt;&lt;/span&gt;，這樣所有的 API 的 visiblity 預設都會是 hidden，接著，只要在想要 Export 的 API 前加上&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt; __attribute__ ((visibility (&quot;default&quot;)))&lt;/span&gt;&lt;/b&gt; 就搞定了。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Android.mk&lt;/h3&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;LOCAL_CFLAGS := -fvisibility=hidden&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
MyLib.cpp&lt;/h3&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#ifdef __GNUC__
  #define DLL_PUBLIC_API __attribute__ ((visibility (&quot;default&quot;)))
  #define DLL_LOCAL_API  __attribute__ ((visibility (&quot;hidden&quot;)))
#else
  #define DLL_PUBLIC_API __declspec(dllexport)
  #define DLL_LOCAL_API
#endif

DLL_PUBLIC_API void MyFunc1() {/*...*/}
DLL_LOCAL_API void MyFunc2() {/*...*/}
void MyFunc3() {/*...*/}&lt;/pre&gt;
將 build 出來的 MyLib.so 丟給 nm parse 看看&lt;br /&gt;
應該就只能在 Symbol Table 裡看到 &lt;b&gt;MyFunc1 &lt;/b&gt;了&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;StackOverflow - &lt;a href=&quot;http://stackoverflow.com/questions/34732/how-do-i-list-the-symbols-in-a-so-file&quot; target=&quot;_blank&quot;&gt;How do I like symbol in a .so file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GCC Wiki - &lt;a href=&quot;http://gcc.gnu.org/wiki/Visibility&quot; target=&quot;_blank&quot;&gt;Visiblity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/11/linux-android-export-api-sharedlibrary.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-1794353485034960177</guid><pubDate>Wed, 30 Oct 2013 08:10:00 +0000</pubDate><atom:updated>2013-12-12T08:16:47.630+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">JNI</category><category domain="http://www.blogger.com/atom/ns#">NDK</category><title>[Android] 在 C Level 用 dlopen 使用 第三方的 Shared Library (.so)</title><description>在 Android 裡，撰寫 JNI C Level 的 code ，不管是想要 load 自己寫的獨立 shared library module (.so)，或是想要把第三方的 shared library 拿來用，都必須要多做一些步驟才能達成。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;h3&gt;
1. 寫個簡單的 libtest.so&lt;/h3&gt;
test.h&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;extern &quot;C&quot;
{
int Add(int num);
}
&lt;/pre&gt;
test.cpp&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;int Add(int num)
{
    return num+1;
}&lt;/pre&gt;
&lt;br /&gt;
Android.mk&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;include $(CLEAR_VARS)
LOCAL_MODULE &amp;nbsp; &amp;nbsp;:= littest
LOCAL_SRC_FILES := test.cpp
include $(BUILD_SHARED_LIBRARY)&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
2. 將已經 compile 好的 libtest.so 放進新的 project 裡&lt;/h3&gt;
首先，要先把已經 build 好的 shared library 放到 Android 專案目錄裡&lt;br /&gt;
而且必須根據平台區分才行：好比 &lt;i&gt;armeabi, armeabi-v7a, x86, mips&lt;/i&gt; ，放好各平台 compile 好的 shared library 後，在 Android.mk 裡必須加一段指令，NDK 才會將這個 shared library 包進 .apk 裡&lt;br /&gt;
&lt;br /&gt;
比如，我想要使用 libtest.so ，將各平台 compile 好的 .so 檔放至 mylib 底下&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;mylib (folder示意)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;armeabi&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;libtest.so&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;aremabi-v7a&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;libtest.so&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;x86&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;libtest.so&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;mips&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;libtest.so&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
就可以利用 NDK 的變數 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;$(TARGET_ARCH_ABI)&lt;/span&gt;&lt;/b&gt; 來區分不同平台的目錄&lt;br /&gt;
Android.mk &lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;include $(CLEAR_VARS)
LOCAL_MODULE := libtest
LOCAL_SRC_FILES := ./mylib/$(TARGET_ARCH_ABI)/libtest.so
include $(PREBUILT_SHARED_LIBRARY)&lt;/pre&gt;
&lt;br /&gt;
Build完後，確認一下 Android 專案下的目錄&lt;span style=&quot;color: #cc0000;&quot;&gt;&lt;b&gt; $PROJECT\lib\&amp;lt;abi&amp;gt;\&lt;/b&gt;&lt;/span&gt;，照理來說應該會找到&lt;b&gt;&amp;nbsp;libtest.so&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
3. 使用 dlopen 控制&amp;nbsp;libtest.so&lt;/h3&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;typedef int (*fnAdd)(int);
void* hDll = dlopen(&quot;/data/data/&amp;lt;package-name&amp;gt;/lib/libtest.so&quot;);
if(hDll) {
    fnAdd add = (fnAdd) dlsym(hDll, &quot;Add&quot;);
    if(fnAdd){
        printf(&quot;10+1=%d\n&quot;, fnAdd(10));
    }
}&lt;/pre&gt;
&lt;br /&gt;
透過 Eclipse 將 .apk 安裝到手機上後，.so 將會放在&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt; /data/data/&amp;lt;package_name&amp;gt;/libtest.so&lt;/span&gt;&lt;/b&gt;，這個 package_name 是定義在 &lt;b&gt;AndroidManifest.xml &lt;/b&gt;裡面的。&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;Reference&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;TARGET_ARCH_ABI : NDK docs/ANDROID-MK.html&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://falldog7.blogspot.com/2013/10/android-c-level-dlopen-shared-library-so.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-4675279201124699502</guid><pubDate>Tue, 08 Oct 2013 09:45:00 +0000</pubDate><atom:updated>2013-12-12T08:22:08.942+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">Eclipse</category><category domain="http://www.blogger.com/atom/ns#">NDK</category><title>[Android] NDK Debug 與 breakpoint 失效的解決之道</title><description>在 Android 開發環境裡，新版的 NDK (目前為 r9 )提供的 GDB Debug C//C++環境其實已經算是很友善的了。不像以前需要下一堆的 command line 才行。&lt;br /&gt;
&lt;br /&gt;
目前我的開發環境：&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;ADT -&amp;nbsp;adt-bundle-windows-x86_64-20130729&lt;/li&gt;
&lt;li&gt;NDK -&amp;nbsp;android-ndk-r9&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
簡單說一下 Debug NDK 的步驟&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
1. Eclipse Preferences&lt;/h2&gt;
設定 &lt;span style=&quot;background-color: #f9cb9c;&quot;&gt;&amp;nbsp;Eclipse Preference | Android | NDK | NDK Location&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
填入正確的 NDK 下載路徑&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
2. 設定 Project property NDK_DEBUG=1&lt;/h2&gt;
&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt;&amp;nbsp;Project Property | C/C++ Builder | Builder Settings&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
取消 Use default build command的選項&lt;br /&gt;
輸入 &lt;b&gt;ndk-build &lt;span style=&quot;color: #cc0000;&quot;&gt;NDK_BUILD=1&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
註：Application.mk or Android.mk 都無需修改，新版的 ADT/NDK 都已經 handle 好其他的設定了&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
3. 設好中斷點&lt;/h2&gt;
在 Eclipse 裡的 C/C++ code，設好中斷點，等著上鉤&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
4. Debug As &quot;Android Native Application&quot;&lt;/h2&gt;
由於目前 ADT 在 Debug 時，同一時間只能選擇 Debug Java or C/C++&lt;br /&gt;
所以如果 Debug As &quot;Android Application&quot;的話，就是 Debug Java level&lt;br /&gt;
如果 Debug As &quot;&lt;span style=&quot;color: #cc0000;&quot;&gt;Android Native Application&lt;/span&gt;&quot;的話，就是 Debug C/C++ level&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
* 問題 *&lt;/h2&gt;
Debug 時設中斷點，可能會出現類似這樣的Error&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;No symbol table is loaded. &amp;nbsp;Use the &quot;file&quot; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
* 原因 *&lt;/h2&gt;
原因是 GDB 在 attach 上去時，如果 shared library(.so) 檔還沒被 load 進來時，所設的中斷點就沒有用了(不確定是 GDB 的限制還是 NDK 的 bug )&lt;br /&gt;
&lt;br /&gt;
所以，如果在 App 執行起來後，馬上就 load shared library 的話，應該是不會遇到這樣的問題。但是為了執行效能，很多 .so 的 module 都會等到使用者用到時才會將它 load 起來，就會遇到這樣的問題了。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
* 解決之道 *&lt;/h2&gt;
假設今天要 Debug&lt;b&gt;&lt;span style=&quot;color: #674ea7;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #45818e;&quot;&gt;libTestNDK.so&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
試著讓 GDB server 暫停住，按下 Debug 的 Suspend 的 button，然後在才能在 GDB Console 輸入指令&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;info shared&lt;/pre&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;From        To          Syms Read   Shared Object Library 
                        No          /system/bin/linker 
0x4012b860  0x4015b184  Yes         D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libc.so 
                        No          libstdc++.so 
                        No          libm.so 
&lt;/pre&gt;
&lt;br /&gt;
上面並沒有顯示&lt;b&gt; &lt;span style=&quot;color: #45818e;&quot;&gt;libTestNDK.so&amp;nbsp;&lt;/span&gt;&lt;/b&gt;，表示&lt;span style=&quot;color: #45818e;&quot;&gt;&lt;b&gt; libTestNDK.so&lt;/b&gt; &lt;/span&gt;還沒被load起來&lt;br /&gt;
試著操作App，確保 Java layer 的 loadLibrary 有被執行到&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;color: #990000;&quot;&gt;java.lang.System.loadLibrary(&quot;TestNDK&quot;);&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
再次讓GDB Suspend，接著再輸入info shared一次&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;From        To          Syms Read   Shared Object Library 
                        No          /system/bin/linker 
0x4012b860  0x4015b184  Yes         D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libc.so 
                        No          libstdc++.so 
                        No          libm.so 
0x69817898  0x69922680  No          D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libTestNDK.so
&lt;/pre&gt;
&lt;br /&gt;
有顯示 &lt;b&gt;&lt;span style=&quot;color: #45818e;&quot;&gt;libTestNDK.so&lt;/span&gt;&lt;/b&gt;，但是 Syms Read 的狀態是 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;No &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
輸入下面的指令，讓 GDB 重新 load sharedlibrary 的 symbol&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;sharedlibrary&lt;/pre&gt;
&lt;br /&gt;
然後再輸入一次 info shared 看結果，狀態會變成 &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;Yes&lt;/span&gt;&lt;/b&gt;，就代表你成功了！&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;0x69817898  0x69922680  Yes          D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libTestNDK.so&lt;/pre&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
再試著去新增中斷點，應該就不會有 Error，可以正常 Debug 了！&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
註：&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;用 Eclipse 去 Debug NDK，其實問題還滿多的&lt;/li&gt;
&lt;li&gt;Android 4.3 不能 Debug 進 NDK，不用試了，直接升級到 4.4 吧!&lt;/li&gt;
&lt;li&gt;真的是很慢....&lt;/li&gt;
&lt;li&gt;有時候中斷了，可是無法 Step Into、Step Next，也無法成功看到 Watch 的參數&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Reference&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CodeProject -&lt;a href=&quot;http://www.codeproject.com/Articles/493043/Why-your-Android-NDK-breakpoints-might-fail-and-ho&quot; target=&quot;_blank&quot;&gt;&amp;nbsp;Why your Android NDK breakpoints might fail and how to fix them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GDB Command - &lt;a href=&quot;http://visualgdb.com/gdbreference/commands/sharedlibrary&quot; target=&quot;_blank&quot;&gt;sharedlibrary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://falldog7.blogspot.com/2013/10/android-ndk-debug-breakpoint.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-8308872365186792618</guid><pubDate>Wed, 14 Aug 2013 06:31:00 +0000</pubDate><atom:updated>2014-09-13T12:01:05.153+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><title>[Win32] 在C/C++中偵測精準的程式時間(Performance Time)</title><description>在Windows底下，要偵測精準的Perfromance Time，可以透過QueryPerformanceFrequency() &amp;amp;&amp;nbsp;QueryPerformanceCounter() 來取得。&lt;br /&gt;
&lt;br /&gt;
由於取得的時間存在LARGE_INTEGER的structure，要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class，讓這個AutoQueryPerformance的instance life-time結束後，自行dump出所花費的時間。&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
AutoQueryPerformance&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#include &quot;windows.h&quot;

// Auto dump the life-time of AutoQueryPerformance
// Ex:
// {
//     AutoQueryPerformance autoQuery(&quot;Test&quot;, true);
//     ...
// } // it will dump message when @autoQuery destroy
class AutoQueryPerformance
{
public:
    AutoQueryPerformance(const char* info, INT loop_count=1, BOOL autoDump=TRUE)
        : m_count_time(0), m_loop_count(loop_count), m_auto(autoDump)
    {
        m_info = info;
        ::ZeroMemory(&amp;amp;m_cpu_freq, sizeof(LARGE_INTEGER));
        ::QueryPerformanceFrequency(&amp;amp;m_cpu_freq);

        if( autoDump )
            begin();
    }
    ~AutoQueryPerformance()
    {
        pause();
        if( autoDump )
            printf(&quot;[AutoQueryPerformance][%s] spend time=%.4f&quot;, m_info.c_str(), getTime());
    }
    inline void begin()
    {
        ::ZeroMemory(&amp;amp;m_start_clock, sizeof(LARGE_INTEGER));;
        ::QueryPerformanceCounter(&amp;amp;m_start_clock);
    }
    inline void pause()
    {
        ::ZeroMemory(&amp;amp;m_cur_clock, sizeof(LARGE_INTEGER));
        ::QueryPerformanceCounter(&amp;amp;m_cur_clock);
        m_count_time += m_cur_clock.QuadPart-m_start_clock.QuadPart;
    }
    inline void stop()
    {
        pause();
        m_count_time = 0;
    }
    inline float getTime()
    {
        return (m_count_time/(float)m_cpu_freq.QuadPart) / m_loop_count;
    }
private:
    LARGE_INTEGER m_cpu_freq;
    LARGE_INTEGER m_start_clock;
    LARGE_INTEGER m_cur_clock;
    LONGLONG      m_count_time;
    INT           m_loop_count;//for for-loop to calculate correct average time
    std::string   m_info;
    BOOL          m_auto;
};
#define AUTO_QUERY_PERFORMANCE(x) AutoQueryPerformance __at_qp = AutoQueryPerformance(x);
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
使用範例&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;void TestingTotalTime(int loop_count)
{
    AutoQueryPerformance ap(&quot;TestingTotalTime&quot;);
    int sum = 0;
    for(int i=0 ; i&amp;lt;loop_count; i++)
       sum += i;
}

void TestingSingleTime(int loop_count)
{
    AutoQueryPerformance ap(&quot;TestingSingleTime&quot;, loop_count);
    for(int i=0 ; i&amp;lt;loop_count; i++)
       //HeavyFunction call here;
}
&lt;/pre&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;MSDN -&amp;nbsp;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;QueryPerformanceFrequency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MSDN -&amp;nbsp;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx&quot; target=&quot;_blank&quot;&gt;QueryPerformanceCounter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/08/win32-cc-performance-time-testnig.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-8922248159212671139</guid><pubDate>Mon, 12 Aug 2013 08:23:00 +0000</pubDate><atom:updated>2015-01-14T18:02:21.847+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">COM</category><category domain="http://www.blogger.com/atom/ns#">DLL</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><title>[Win32/COM] Use COM DLL without registered</title><description>依照Windows COM元件的使用方法，應該要將COM DLL註冊後，即可在程式中，以CoCreateInstance()帶入CLSID、IID就可以將該DLL自動load起來，創建該class的instance了。&lt;br /&gt;
&lt;br /&gt;
但是在開發時，實際上總是沒這麼美好，註冊DLL其實是很麻煩的，新舊相容性，開發中的版本等等的問題，而走manifest其實可以避開註冊這條路，但是今天我需要寫一個COM module讓別人使用，而這個COM module在AP裡是走manifest的，所以不會被註冊，連帶的module會用到其他的Library也不走註冊這條路，而因為一些其他的原因，也不能將此Library寫入manifest裡，只能尋求其他途徑了。&lt;br /&gt;
&lt;br /&gt;
由於COM的DLL都會link到一些基本的COM Library，所以是有一些export的API可以繞過註冊來create COM instance的，直接參考以下的Sample Code吧。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// {599D2F5F-BA8D-4009-941C-A5393EBD5C58}
DEFINE_GUID(CLSID_MyCOM, 
0x599d2f5f, 0xba8d, 0x4009, 0x94, 0x1c, 0xa5, 0x39, 0x3e, 0xbd, 0x5c, 0x58);

// {4C452CB2-469C-4236-AE5C-F48A28EC0870}
DEFINE_GUID(IID_IMyCOM, 
0x4c452cb2, 0x469c, 0x4236, 0xae, 0x5c, 0xf4, 0x8a, 0x28, 0xec, 0x8, 0x70);

HRESULT CreateInstance(IMyCOM** pMyCom)
{
    HMODULE hDll = LoadLibrary(&quot;MY_COM.dll&quot;);//Need refine by your self
    if(hDll)
    {
        //////////////////////////////////////////////////////////////////////////
        // Initial COM instance without register
        //   Try to load COM DLL directly, and call DllGetClassObject to get IID_IClassFactory
        //   And Create COM instance by IID_IClassFactory
        // -----------------------------------------------------------------------
        //   HRESULT hr = CoCreateInstance(CLSID_MyCOM, 
        //                                 NULL, 
        //                                 CLSCTX_INPROC_SERVER, 
        //                                 IID_IMyCOM, 
        //                                 (PVOID*)&amp;amp;pMyCom);
        //////////////////////////////////////////////////////////////////////////
        CComPtr&amp;lt;IClassFactory&amp;gt; spFactory;

        // Get address of DllGetClassObject exported method
        PDLLGETCLSOBJ pDllGetCLSObj = (PDLLGETCLSOBJ)GetProcAddress(hDll, &quot;DllGetClassObject&quot;);

        // Call DllGetClassObject and get the proper IClassFactory interface
        HRESULT hr = pDllGetCLSObj(CLSID_MyCOM, IID_IClassFactory, reinterpret_cast&amp;lt;PVOID*&amp;gt;(&amp;amp;spFactory));
        if( FAILED(hr) )
        {
            printf(__FUNCTION__&quot; [Err] Can&#39;t get spFactory hr=%X&quot;, hr);
            return E_FAIL;
        }

        // Create an instance of IMyCOM
        hr = spFactory-&amp;gt;CreateInstance(NULL, IID_IMyCOM, (PVOID*)pMyCom);
        if( FAILED(hr) )
        {
            printf(__FUNCTION__&quot; [Err] Init IMyCOM Fail! hr=%X&quot;, hr);
            return E_FAIL;
        }
    }
    else
    {
        return E_FAIL;
    }
    return S_OK;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Reference:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;StackOverflow -&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions/2466138/windows-c-how-to-use-a-com-dll-which-is-not-registered&quot; target=&quot;_blank&quot;&gt;Windows/C++: how to use a COM dll which is not registered&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/08/win32com-use-com-dll-without-registered.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-1120481279538215948</guid><pubDate>Mon, 12 Aug 2013 07:18:00 +0000</pubDate><atom:updated>2013-08-12T15:19:23.455+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Python</category><title>[Python] 使用objgraph找出memory leak(circular reference)</title><description>在Python的世界裡，所有的東西都是Object，而控制Object的life cycle靠的就是reference的機制，一個簡單的assignement (=等號)，或是function call就會讓Object的reference count自動加1。&lt;br /&gt;
而當Object的reference count減至0的時候，Python的GC會找時間把這些Object清除掉。&lt;br /&gt;
&lt;br /&gt;
對Python而言，memory leak產生的可能性有兩種&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Circular reference&lt;/li&gt;
&lt;li&gt;Referece在global的變數或是module上&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
其實有些tool可以找到這種reference的關係，這邊介紹的是 &lt;span style=&quot;color: #cc0000;&quot;&gt;&lt;b&gt;&lt;i&gt;objgraph&lt;/i&gt;&lt;/b&gt; &lt;/span&gt;- &lt;a href=&quot;http://mg.pov.lt/objgraph/&quot; target=&quot;_blank&quot;&gt;官網&lt;/a&gt;，視覺化的Reference結果圖，讓人一目瞭然。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
可以在下載後安裝&lt;/div&gt;
&lt;pre class=&quot;cmd&quot;&gt;pip install objgraph
&lt;/pre&gt;
&lt;div&gt;
或是直接將壓縮檔內的objgraph.py解壓放在執行檔旁，因為objgraph就這麼一個檔案！&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
不過，為了將objgraph解析後的狀態轉成圖檔，還需要安裝另一個tool - &lt;a href=&quot;http://www.graphviz.org/&quot; target=&quot;_blank&quot;&gt;graphviz&lt;/a&gt;，這個是跟python無關的tool，只是objgraph輸出一個config檔，透過subprocess執行graphviz去讀取這個config檔，然後輸出最後關係圖的圖檔。接著可以透過關係圖檔找到應該解除reference link的地方，再一一破解，應該就可以解開memory leak了。&lt;br /&gt;
&lt;br /&gt;
以下示範較常用的show_backrefs()&lt;br /&gt;
還有其他的API可直接參照objgraph.py裡&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Example: Value object reference 在 Container 裡&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;class Value(object):
    def __init__(self, v):
        object.__init__(self)
        self.v = v
    def get(self):
        return self.v
    def set(self, v):
        self.v = v
        
class Container(object):
    def __init__(self):
        object.__init__(self)
        self.children = []
    def get(self, idx):
        return self.children[idx]
    def pop(self):
        c = self.children.pop()
        return c
    def push(self, c):
        return self.children.append(c)
        
if __name__== &#39;__main__&#39;: 
    c1 = Container()
    c1.push(Value(100))
    
    import objgraph
    objgraph.show_backrefs([c.get(0)], filename=&#39;test.png&#39;)
&lt;/pre&gt;
輸出結果圖：&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDRwZnmsVdz-52yhNL3ls9A4cWRaz0f6p2mZTBxomjP5SvFWTX_0GZgfI2TjjhoaQ3_LKHVmbF8u4pzzNKDM9P4knYxIywrQBweLMoPVJ2DaRhz7TVvfdTUTWbMGlxYeLDkc1FmX4pMxVS/s1600/base.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDRwZnmsVdz-52yhNL3ls9A4cWRaz0f6p2mZTBxomjP5SvFWTX_0GZgfI2TjjhoaQ3_LKHVmbF8u4pzzNKDM9P4knYxIywrQBweLMoPVJ2DaRhz7TVvfdTUTWbMGlxYeLDkc1FmX4pMxVS/s320/base.png&quot; width=&quot;292&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h4&gt;
Example 2: &amp;nbsp;2個Container同時reference在同一個Value object&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;if __name__== &#39;__main__&#39;: 
    c1 = Container()
    c1.push(Value(100))
    
    c2 = Container()
    c2.push(c1.get(0))

    import objgraph
    objgraph.show_backrefs([c.get(0)], filename=&#39;test.png&#39;)
&lt;/pre&gt;
輸出結果圖：&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhacfjfhcE4ie85XPHAkSciZ7AjeLikcOUBo6oeAf6hHpc0yVd9XZLzYNa5s_naQ1XZvjGqg3kEWsaN3OxreHhjYB9eSm3HtGNHIciQ72J2xoO1dV3bZI0Ihq44USnRluI5yrSddx_3GIDi/s1600/base2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;173&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhacfjfhcE4ie85XPHAkSciZ7AjeLikcOUBo6oeAf6hHpc0yVd9XZLzYNa5s_naQ1XZvjGqg3kEWsaN3OxreHhjYB9eSm3HtGNHIciQ72J2xoO1dV3bZI0Ihq44USnRluI5yrSddx_3GIDi/s320/base2.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Example 3: circular reference&lt;/h4&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;if __name__== &#39;__main__&#39;: 
    c1 = Container()
    v = Value(c1)
    c1.push(v) #circular reference
    
    import objgraph
    objgraph.show_backrefs([c1.get(0)], max_depth=5, filename=&#39;test.png&#39;)
&lt;/pre&gt;
輸出結果圖：&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu_f2xZdu5DpbaVp5wNcSkJa1NG3LxbXq5HzHd5Y8gcBxgrC4mXe2xTYly_GqovRjcOwpAIvbzV0paGeTJ7IOjNFiiDkz2_0yzayGhN2eQS1am5ZizxlDM1PNzCYAQl5-vQTAvdf80-SNF/s1600/test.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;228&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu_f2xZdu5DpbaVp5wNcSkJa1NG3LxbXq5HzHd5Y8gcBxgrC4mXe2xTYly_GqovRjcOwpAIvbzV0paGeTJ7IOjNFiiDkz2_0yzayGhN2eQS1am5ZizxlDM1PNzCYAQl5-vQTAvdf80-SNF/s320/test.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Reference:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;objgraph - &lt;a href=&quot;http://mg.pov.lt/objgraph/&quot; target=&quot;_blank&quot;&gt;official site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;graphviz - &lt;a href=&quot;http://www.graphviz.org/&quot; target=&quot;_blank&quot;&gt;offcial site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PyPI - &lt;a href=&quot;https://pypi.python.org/pypi/objgraph&quot; target=&quot;_blank&quot;&gt;objgraph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2013/08/python-objgraph-memory-leak-circular.html</link><author>noreply@blogger.com (Falldog)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDRwZnmsVdz-52yhNL3ls9A4cWRaz0f6p2mZTBxomjP5SvFWTX_0GZgfI2TjjhoaQ3_LKHVmbF8u4pzzNKDM9P4knYxIywrQBweLMoPVJ2DaRhz7TVvfdTUTWbMGlxYeLDkc1FmX4pMxVS/s72-c/base.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-3114757969408171708</guid><pubDate>Thu, 18 Jul 2013 08:50:00 +0000</pubDate><atom:updated>2013-07-18T17:02:02.742+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Jython</category><title>[Jython] Use JNA Read/Write Windows Registry </title><description>最近用Sikuli開發，Run Script時需要讀寫Windows的Registry，由於Sikuli script是用Jython的，而Jython裡並不像Python支援Read/Write Windows Registry，所以必須用一些其他的Library才行&lt;br /&gt;
&lt;br /&gt;
而其中一個方法就是用&lt;a href=&quot;https://github.com/twall/jna&quot; target=&quot;_blank&quot;&gt;JNA&lt;/a&gt;&lt;br /&gt;
下載最新的JNA與JNA-Platform&lt;br /&gt;
放到要執行的Script旁，或是放到Jython的目錄裡&lt;br /&gt;
&lt;br /&gt;
以下的範例，將jna-3.5.1.jar與jna-platform-3.5.1.jar放到Sample.py旁，以Jython執行&lt;br /&gt;
Sample.py&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;import os
import sys
folder = os.path.dirname(os.path.abspath(__file__))

# load JavaLib jna/platform
sys.path.append(os.path.join(folder, &#39;jna-3.5.1.jar&#39;))
sys.path.append(os.path.join(folder, &#39;jna-platform-3.5.1.jar&#39;))

# Read
from com.sun.jna.platform.win32 import Advapi32Util, WinReg
path = Advapi32Util.registryGetStringValue( \
    WinReg.HKEY_LOCAL_MACHINE, 
    r&#39;Software\CyberLink\ColorDirector2&#39;, 
    &#39;InstallPath&#39; )

print path.encode(sys.getfilesystemencoding())
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/twall/jna&quot; target=&quot;_blank&quot;&gt;JNA Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://twall.github.io/jna/3.5.1/javadoc/&quot; target=&quot;_blank&quot;&gt;JNA - 3.5.1 JavaDoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://twall.github.io/jna/4.0/javadoc/&quot; target=&quot;_blank&quot;&gt;JNA - 4.0 JavaDoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/62289/read-write-to-windows-registry-using-java&quot; target=&quot;_blank&quot;&gt;StackOverflow - Read/Write Windows Registry in Java&lt;/a&gt;&amp;nbsp;(還有其他方法可以參考)&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/07/jython-use-jna-read-write-windows.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-1041069732950348878</guid><pubDate>Wed, 17 Jul 2013 03:08:00 +0000</pubDate><atom:updated>2015-01-14T18:02:41.812+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">DLL</category><category domain="http://www.blogger.com/atom/ns#">Python</category><category domain="http://www.blogger.com/atom/ns#">SWIG</category><title>[Python] Windows底下 使用SWIG呼叫C/C++的function</title><description>使用Python的script language的特性，開發起來實在是又快又舒服，但是Python有個致命的缺點就是&lt;a href=&quot;http://docs.python.org/2/c-api/init.html#thread-state-and-the-global-interpreter-lock&quot;&gt;GIL&lt;/a&gt;，在Multi-Thread的機制下，有了這個GIL的限制，感覺Multi-Thread就被俺掉一半了。照理來說heavy的blocking code應該要寫在另一條thread，並且放掉GIL，讓其他的thread有時間去做事才對。透過Python轉call進C/C++的function後，才有機會讓heavy的function放掉Python的GIL。&lt;br /&gt;
&lt;br /&gt;
不過，本篇的重點在於介紹如果讓Python呼叫C/C++ level的function，有機會的話，再介紹一下GIL好了。目前其實有很多Tool提供這樣的功能，包括SWIG、Boost.Python、Robin…等等，這邊就介紹一下SWIG的用法。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
先簡單說明一下SWIG是怎麼辦到的&lt;br /&gt;
1. 將我們C/C++ level的code包在一個&quot;&lt;b&gt;Sample&lt;/b&gt;&quot; &lt;b&gt;DLL project&lt;/b&gt;裡&lt;br /&gt;
2. 寫一份interface的&lt;i&gt;Sample.i&lt;/i&gt;檔給SWIG.exe parse後產生出一個&lt;i&gt;Sample_wrap.c&lt;/i&gt;與&lt;i&gt;Sample.py&lt;/i&gt;檔&lt;br /&gt;
3. 我們再將&lt;i&gt;Sample_wrap.c&lt;/i&gt;加進DLL project裡，一起compile成&lt;i&gt;_Sample.pyd&lt;/i&gt;&lt;br /&gt;
4. 在Python code中import Sample 就能呼叫Sample裡的API了&lt;br /&gt;
所以，其實SWIG做的事情只是parse &lt;i&gt;Sample.i&lt;/i&gt;檔，產生wrapper檔：&lt;i&gt;Sample_wrap.c&lt;/i&gt;，DLL project連著這個wrapper檔一起compile的話，就可以讓Python層呼叫執行了。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
1. 下載SWIG&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.swig.org/&quot; target=&quot;_blank&quot;&gt;SWIG官網&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sourceforge.net/projects/swig/files/&quot; target=&quot;_blank&quot;&gt;SourceForge - SWIG下載&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sourceforge.net/projects/swig/files/swigwin/&quot; target=&quot;_blank&quot;&gt;SourceForge - SWIG-Windows版下載&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
目前最新的SWIG已經&lt;a href=&quot;http://sourceforge.net/projects/swig/files/swigwin/swigwin-2.0.10/&quot;&gt;2.0.10&lt;/a&gt;版了，下載後，解壓縮，我們在compile project時，只需要其中的&lt;i&gt;swig.exe&lt;/i&gt;檔&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;
2. 設定VC的Include, Library, Execute path&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
為了在C/C++ code裡撰寫CPython，必須指定Python的&lt;b&gt;Include, Library path&lt;/b&gt;&lt;br /&gt;
而指定&lt;b&gt;Execute path&lt;/b&gt;是為了在Project property使用swig時，不需要輸入絕對路徑&lt;br /&gt;
&lt;br /&gt;
假如電腦裡安裝的是Python 2.7&lt;br /&gt;
在Window裡的預設路行就是&lt;i&gt;C:\Python27&lt;/i&gt;&lt;br /&gt;
在&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt;Tool | Options | Projects and Solutions | VC++ Directories&lt;/span&gt;裡新增&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Include files&lt;/b&gt; : &lt;i&gt;C:\Python27\include&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Library files&lt;/b&gt; : &lt;i&gt;C:\Python27\libs&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Executable files&lt;/b&gt; : &lt;i&gt;C:\swigwin-2.0.10\&lt;/i&gt; (第一步中解壓縮的路徑)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;h2&gt;
3. 建立C/C++ DLL Project&lt;/h2&gt;
我以VC2008(其他版本也可以)，建立一個Win32的C/C++的&lt;b&gt;DLL Project&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwR2lTYC0laWzKyoRAOc8hUNq7u26W8Iadromf4lq1F2ts9j9ypmPhEksVSE5nWmcaI1Ui9AFLBgBQmYLdnO5OdBpnEuBCKQJWxJMrJuIWplyLgeW7ABwHDvbzlsvWrBoPye1i2qRPfrWV/s1600/Swig-NewProject.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwR2lTYC0laWzKyoRAOc8hUNq7u26W8Iadromf4lq1F2ts9j9ypmPhEksVSE5nWmcaI1Ui9AFLBgBQmYLdnO5OdBpnEuBCKQJWxJMrJuIWplyLgeW7ABwHDvbzlsvWrBoPye1i2qRPfrWV/s320/Swig-NewProject.png&quot; height=&quot;271&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
選擇&lt;b&gt;&quot;Emtpy Project&quot;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
若不選擇&quot;Empty Project&quot;也沒關係，記得要將&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; Project Property | C/C++ | Precompiled Headers | Create/Use Precompiled Header &lt;/span&gt;切換成&lt;b&gt; &quot;Not Using Precompiled Headers&quot;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
4. 撰寫C/C++的API - Sample.h, Sample.cpp&lt;/h2&gt;
Sample.h&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#include &quot;Python.h&quot;

int AddOne(int n);
int Sqrt(int n);
PyObject* SqrtInPyObj(PyObject* obj);

&lt;/pre&gt;
&lt;br /&gt;
Sample.cpp&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#include &quot;Sample.h&quot;

int AddOne(int n)
{
    return n+1;
}

int Sqrt(int n)
{
    return n*n;
}

PyObject* SqrtInPyObj(PyObject* obj)
{
    int n = PyInt_AsLong(obj);
    return Py_BuildValue(&quot;i&quot;, n*n);
}

&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
5. 設置interface檔 - Sample.i&lt;/h2&gt;
由於SWIG需要此interface檔來產生wrapper的cxx檔，因此需撰寫一個&amp;nbsp;&lt;i&gt;Sample.i&amp;nbsp;&lt;/i&gt;檔加到Project裡，這樣才能在Compile後即時update最新的pyd檔&lt;br /&gt;
右鍵選擇&amp;nbsp;&lt;i&gt;Sample.i&amp;nbsp;&lt;/i&gt;的Property，設置&lt;b&gt;Custom Build Step&lt;/b&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvpS1udCXCIH8npl6fLgVkg1YtpYekZM5wxr6jYC9PiZ6WwR29akZyaUc-TnhG59pve9og0ETYdGPyM8kA2VIm4DVw52Mu7V69Kl6ydSQqi_ZLSjj90ndfdXbCQH49zkf7lYlszW8QHIZk/s1600/SWIG-SampleI.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvpS1udCXCIH8npl6fLgVkg1YtpYekZM5wxr6jYC9PiZ6WwR29akZyaUc-TnhG59pve9og0ETYdGPyM8kA2VIm4DVw52Mu7V69Kl6ydSQqi_ZLSjj90ndfdXbCQH49zkf7lYlszW8QHIZk/s320/SWIG-SampleI.png&quot; height=&quot;249&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Example : c, output file為&lt;i&gt;Sample_wrap.c&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Command Line&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;swig.exe -python -o&amp;nbsp;$(ProjectDir)\$(InputName)_wrap.c &quot;$(InputPath)&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;Outputs&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;$(InputName)_wrap.c&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Example : c++, output file為&lt;i&gt;Sample_wrap.cxx&lt;/i&gt;, 記得加上&lt;b&gt;-c++&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Command Line&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;swig.exe -c++ -python -o&amp;nbsp;$(ProjectDir)\$(InputName)_wrap.cxx &quot;$(InputPath)&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;Outputs&lt;/b&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;$(InputName)_wrap.cxx&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Sample.i範例&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;%module Sample 

%{
#include &quot;Sample.h&quot;
%}

%include &quot;Sample.h&quot;
&lt;/pre&gt;
&lt;div style=&quot;font-family: &#39;Times New Roman&#39;; white-space: normal;&quot;&gt;
interface檔尚有許多的功能，有興趣的人可以再深入研究 -&amp;nbsp;&lt;a href=&quot;http://www.swig.org/Doc2.0/Python.html#Python&quot;&gt;SWIG 2.0 Python Document&lt;/a&gt;&lt;br /&gt;
這邊就不多做著墨了&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
6. 加入Sample_wrap.cxx or Sample_wrap.c至Project中&lt;/h2&gt;
在做完以上的步驟後，可以先compile一次，就會透過&amp;nbsp;&lt;i&gt;Sample.i&amp;nbsp;&lt;/i&gt;的Custom Build Step產生&lt;i&gt;Sample_wrap.cxx&lt;/i&gt;檔，再將此當加入Project中一起Compile&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
7. Compile&lt;/h2&gt;
點選Project Property，修改&lt;br /&gt;
&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; Linker | Output File&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;$(OutDir)\_$(ProjectName).pyd&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
讓最後的檔案輸出成&lt;i&gt;_Sample.pyd&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
點選Project Property，修改&lt;br /&gt;
&lt;span style=&quot;background-color: #f9cb9c;&quot;&gt; C/C++ | Preprocessor | Preprocessor Definitions&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
新增 &lt;b&gt;&lt;i&gt;__WIN32__&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
以上都完成後，就可以開始Compile了&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
8. Import Python module&lt;/h2&gt;
將Compile過後的&lt;i&gt;Sample.py&lt;/i&gt;與&lt;i&gt;_Sample.pyd&lt;/i&gt;複製到你的Python script旁，執行應該就可以看到結果了！&lt;br /&gt;
Example :&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;import Sample
print Sample.AddOne(1) # &amp;gt;&amp;gt;&amp;gt; 2
print Sample.Sqrt(2) # &amp;gt;&amp;gt;&amp;gt; 4
print Sample.Sqrt(3) # &amp;gt;&amp;gt;&amp;gt; 9
print Sample.SqrtInPyObj(2) # &amp;gt;&amp;gt;&amp;gt; 4
print Sample.SqrtInPyObj(3) # &amp;gt;&amp;gt;&amp;gt; 9
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2013/07/python-swig-c-function.html</link><author>noreply@blogger.com (Falldog)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwR2lTYC0laWzKyoRAOc8hUNq7u26W8Iadromf4lq1F2ts9j9ypmPhEksVSE5nWmcaI1Ui9AFLBgBQmYLdnO5OdBpnEuBCKQJWxJMrJuIWplyLgeW7ABwHDvbzlsvWrBoPye1i2qRPfrWV/s72-c/Swig-NewProject.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-7504621128361359859</guid><pubDate>Tue, 25 Jun 2013 06:28:00 +0000</pubDate><atom:updated>2015-01-14T18:02:52.785+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Eclipse</category><category domain="http://www.blogger.com/atom/ns#">PHP</category><title>[PHP] Debug PHP by Eclipse with PDT PlugIn</title><description>強大的Eclipse開發社群，提供了PHP的debug功能 - PHP Development Tool (PDT) PlugIn，可以執行並下中斷點，對PHP開發者而言著實是一大福音！&lt;br /&gt;
&lt;br /&gt;
PDT套件可以視為是debug的client端，而server端的話，就需要在PHP安裝extension才行，目前PDT支援的包括(1)&lt;a href=&quot;http://www.zend.com/en/company/community/pdt/&quot; target=&quot;_blank&quot;&gt;Zend Debugger&lt;/a&gt; (2)&lt;a href=&quot;http://xdebug.org/&quot; target=&quot;_blank&quot;&gt;XDebug&lt;/a&gt;，以下就介紹PDT以Zend Debugger的方式進行debug ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
1. 安裝Eclipse&lt;/h2&gt;
從官網安裝最新版乾淨的 &lt;b&gt;&lt;a href=&quot;http://www.eclipse.org/downloads/&quot; target=&quot;_blank&quot;&gt;Eclipse Classic&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
或是安裝&lt;a href=&quot;http://www.zend.com/en/company/community/pdt/downloads&quot; target=&quot;_blank&quot;&gt;Eclipse+PDT一體成形懶人包&lt;/a&gt;&amp;nbsp;(這個懶人包是由Zend提供的，所以Eclipse版本可能稍舊)，若是安裝這版的話，就可以省略&lt;u&gt;步驟2&lt;/u&gt;了&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
2. 安裝Eclipse PDT套件&lt;/h2&gt;
由於現在&lt;b&gt;PDT&lt;/b&gt;現在是由Eclipse官方maintain的套件，所以透過Eclipse內建的Install PlugIn的功能就能直接下載了呢。&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
首先，到&lt;span style=&quot;background-color: #fce5cd;&quot;&gt; &lt;b&gt;Help | Install New Software ...&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQQ0-XxPJDqutKj2xiJZYZKb7a3Hpwh7wRDJmafw8plFld8cLKIg3WVovAlvD8Q99y_QhjVGXKbBuE8oAa5DJUhMkoiDMbg40T1KXJBy1QXMESFNKoQWRPaEMeq1OGYq30MxzPUlaL_mKu/s1600/Eclipse-InstallNewSoftware.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQQ0-XxPJDqutKj2xiJZYZKb7a3Hpwh7wRDJmafw8plFld8cLKIg3WVovAlvD8Q99y_QhjVGXKbBuE8oAa5DJUhMkoiDMbg40T1KXJBy1QXMESFNKoQWRPaEMeq1OGYq30MxzPUlaL_mKu/s320/Eclipse-InstallNewSoftware.png&quot; height=&quot;172&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
選擇Eclipse官網的release URL，以我自己的Eclipse為例，版號代稱為「&lt;i&gt;Juno&lt;/i&gt;」，所以URL前面的名稱就會有「&lt;i&gt;Juno&lt;/i&gt;」的名稱&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG2MP6k8r3QWI6NTmxfHc3QAM8O-WUIM6hG39rQUAe36tcfwTobfASmEOb5_3ArVG-FRiWuGoom57xH48GqpuTRqyMi6t5ZZmhg1nxTBjHMXU_MWvW0psPIMN5DGVTh-ZUKs2UeOMlI5Rn/s1600/Eclipse-InstallNewSoftware-Juno.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG2MP6k8r3QWI6NTmxfHc3QAM8O-WUIM6hG39rQUAe36tcfwTobfASmEOb5_3ArVG-FRiWuGoom57xH48GqpuTRqyMi6t5ZZmhg1nxTBjHMXU_MWvW0psPIMN5DGVTh-ZUKs2UeOMlI5Rn/s320/Eclipse-InstallNewSoftware-Juno.png&quot; height=&quot;298&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
選擇後，就會出現支援的PlugIn，選擇 &lt;span style=&quot;background-color: #fce5cd;&quot;&gt;Web, XML, Java EE and OSGi Enterprise Development | PHP Development Tools(PDT)&lt;/span&gt;，然後一直按Next後，重開Eclipse就完成了。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQkOJ1NKW79fe0J2rWRQdCPb9UCpoOOn4KVWF_H5RjiQLR6l_SnS28GQa7jzDpisidRNDCEoLfUEf_4n6YPvwRMMaLZIlqn3kEVmYjd-vP8ryJ_vO3fcZq1HR-rRuyUMXMNTAWcxB9JiP1/s1600/Eclipse-InstallNewSoftware-PDT.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQkOJ1NKW79fe0J2rWRQdCPb9UCpoOOn4KVWF_H5RjiQLR6l_SnS28GQa7jzDpisidRNDCEoLfUEf_4n6YPvwRMMaLZIlqn3kEVmYjd-vP8ryJ_vO3fcZq1HR-rRuyUMXMNTAWcxB9JiP1/s320/Eclipse-InstallNewSoftware-PDT.png&quot; height=&quot;314&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
3. 安裝Zend Debugger&lt;/h2&gt;
&lt;h3&gt;
3.1 下載Zend Debugger&lt;/h3&gt;
進入Zend Debugger的下載網站，選擇下載&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;Studio Web Debugger&lt;/span&gt;&lt;/b&gt;，可能要註冊他們網站的會員才能下載，有點麻煩。&lt;br /&gt;
下載下來後，將它解壓縮，選出適合自己的環境的版本(OS/PHP)，將&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;ZendDebugger.dll&lt;/span&gt;&lt;/b&gt;複製到&lt;b style=&quot;font-style: italic;&quot;&gt;{PHP install path}/ext&amp;nbsp;&lt;/b&gt;(32bit or 64bit的版本不要抓錯了！)&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
3.2 修改php.ini&lt;/h3&gt;
以下這範例是我自己放的路徑，記得改成你放Zend Debugger.dll的路徑&lt;i&gt;&lt;b&gt;{PHP install path}/ext&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;pre class=&quot;cmd&quot;&gt;zend_extension_ts = C:/AppServ/php5/ext/ZendDebugger.dll ;Note : use &quot;/&quot; instead of &quot;\&quot;
zend_debugger.allow_hosts=127.0.0.1
zend_debugger.expose_remotely=always 
&lt;/pre&gt;
allow_hosts填多組ip的話，要用逗號&quot;&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;,&lt;/span&gt;&lt;/b&gt;&quot;分開&lt;br /&gt;
&lt;h3&gt;
3.3 Copy dummpy.php&lt;/h3&gt;
將Zend Debugger壓縮檔裡附的&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;dummpy.php&lt;/span&gt;&lt;/b&gt;複製到Apache的Document Root&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
3.4 重新啟動Apache server&lt;/h3&gt;
檢查一下phpinfo，應該可以看到Zend Debbuger的資訊&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVB1rv2TmxR0_r4L4nPtrAaNgyWDk14xO-OeeGoeABt8qWl_YwLYVUuC8UZzemBz9idE95KyR3gCTRl0bVesOqs5sCo8kd1PQ8cPY9g7XhW9JO4qSTqym6HysVgK4agZggmzJNlOCHVqwA/s1600/ZendDebugger.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVB1rv2TmxR0_r4L4nPtrAaNgyWDk14xO-OeeGoeABt8qWl_YwLYVUuC8UZzemBz9idE95KyR3gCTRl0bVesOqs5sCo8kd1PQ8cPY9g7XhW9JO4qSTqym6HysVgK4agZggmzJNlOCHVqwA/s320/ZendDebugger.png&quot; height=&quot;157&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
4. Debug PHP Project&lt;/h2&gt;
以上設定完成後，就可以開始PHP Debug之旅了，在New Project時，就可以選擇&lt;b&gt;PHP Project&lt;/b&gt;了，指定到Apache的Document Root裡的資料夾&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmmXX7cORx6hNsd8-kk3zxkh4LVNDpfukllzvikohNKqAnVJHpo5nievcwb9wMtxULog_vt_Fwk9iBBavwKTUASg-OA9ZL4PextE6IGweyCb8sRycwtzjsp4rMa4MaZHcHLFxHYpIO9ot8/s1600/Eclipse-PHPProject.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmmXX7cORx6hNsd8-kk3zxkh4LVNDpfukllzvikohNKqAnVJHpo5nievcwb9wMtxULog_vt_Fwk9iBBavwKTUASg-OA9ZL4PextE6IGweyCb8sRycwtzjsp4rMa4MaZHcHLFxHYpIO9ot8/s320/Eclipse-PHPProject.png&quot; height=&quot;315&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
PHP Project create完成後，就可以開始debug了，執行Eclipse的&lt;span style=&quot;background-color: #fce5cd;&quot;&gt;Debug As | PHP Web Application&lt;/span&gt;就大功告成了！&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Eclipse introduce page&amp;nbsp;&lt;a href=&quot;http://www.eclipse.org/pdt/downloads/&quot;&gt;download PDT all in one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Zend Debugger - &lt;a href=&quot;http://static.zend.com/topics/Zend-Debugger-Installation-Guide-050211.pdf&quot;&gt;installation guid [PDF]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PDT Wiki - &lt;a href=&quot;http://www.thierryb.net/pdtwiki/index.php?title=Using_PDT_:_Installation_:_Installing_the_Zend_Debugger&quot; target=&quot;_blank&quot;&gt;Install Zend Debugger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/06/php-debug-in-eclipse-in-pdt-plugin.html</link><author>noreply@blogger.com (Falldog)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQQ0-XxPJDqutKj2xiJZYZKb7a3Hpwh7wRDJmafw8plFld8cLKIg3WVovAlvD8Q99y_QhjVGXKbBuE8oAa5DJUhMkoiDMbg40T1KXJBy1QXMESFNKoQWRPaEMeq1OGYq30MxzPUlaL_mKu/s72-c/Eclipse-InstallNewSoftware.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-7205039297105551767</guid><pubDate>Thu, 06 Jun 2013 02:24:00 +0000</pubDate><atom:updated>2013-06-06T10:28:14.550+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Eclipse</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Sikuli</category><title>[Sikuli] Compile Sikuli-IDE source code in Eclipse</title><description>&lt;a href=&quot;http://www.sikuli.org/&quot;&gt;Sikuli&lt;/a&gt;是新堀起的Programming Language，以圖象化的方式來coding真的是一大圖破創新的想法。重點是...還是台灣人做的呢！Sikuli是Open Source的，所以有不少人為這個Project供獻一己之力，最近公司的Project用它來做AutoTest，整個很給力，決定來compile它的source code來玩看看，雖然說很久沒寫Java了.... XD&lt;br /&gt;
&lt;br /&gt;
Sikuli的Project切成兩部分，一個是整個核心的Sikuli-API是以Java、C++為主，另一個是開發平台的Sikuli-IDE是純Java的Project，由於整個核心API切出來成一個單獨的Project，所以如果想自己寫一個Java的程式直接使用Sikuli-API是可行的！詳見：&lt;a href=&quot;http://doc.sikuli.org/faq/030-java-dev.html&quot;&gt;How to use Sikuli Script in your Java Program?&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
也由於Sikuli API模組化的關係，目前Sikuli Script語法是Python，以後可能還會陸續支援其他語言吧。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;
1. 安裝Eclipse&lt;/h2&gt;
&lt;a href=&quot;http://www.eclipse.org/downloads/&quot;&gt;Eclipse官網 - Download&lt;/a&gt;&lt;br /&gt;
安裝可以compile Java的Eclipse版本，應該都可以&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
2. 下載Sikuli Library&lt;/h2&gt;
目前Sikuli版本是1.0.0，由於本篇介紹的是compile Sikuli-IDE，所以並不打算自己compile Sikuli-Script，可以直接下載已經release的版本即可&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://launchpad.net/sikuli/+download&quot;&gt;Sikuli Download Page&lt;/a&gt;&lt;br /&gt;
下載 &lt;a href=&quot;https://launchpad.net/sikuli/sikuli-api/1.0.0/+download/Sikuli-IDE-1.0.0-Win32.zip&quot;&gt;Sikuli-IDE-1.0.0-Win32.zip&lt;/a&gt;後解壓縮&lt;br /&gt;
(其他還有Win64, Linux32/64, Mac的版本可載)&lt;br /&gt;
基本上，裡面即包含已經build好的sikuli-script.jar、以及其他開發所需要的Library&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
3. 建立Eclipse的Sikuli-IDE project&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;File | New | Project 選擇 Java Project&lt;/li&gt;
&lt;li&gt;JRE 選擇JavaSE-1.6 (1.7應該也可以)&lt;/li&gt;
&lt;li&gt;Finish&lt;/li&gt;
&lt;li&gt;點選 Project Property&lt;/li&gt;
&lt;li&gt;進入 Project Property | Java Build Path | Libraries&lt;/li&gt;
&lt;li&gt;Add External JARs - 選擇&quot;Step 2&quot;裡下載解壓後所有的&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt; *.jar&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;檔 (不包含sikuli-ide.jar)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
4. 設定Environment&lt;/h2&gt;
如果已經安裝過Sikuli安裝版的話，版本不要差太多的話，應該是可以不用設定&lt;br /&gt;
設定環境變數&lt;i&gt;%SIKULI_HOME%&lt;/i&gt;與&lt;i&gt;%PATH%&lt;/i&gt; (只有&lt;b&gt;Windows&lt;/b&gt;底下才需要設定&lt;i&gt;%PATH%&lt;/i&gt;)&lt;br /&gt;
你可以選擇修改系統的環境變數，或是設定Eclipse Project的環境變數，設定Eclipse Project對環境似乎比較乾淨，以下簡單說明一下&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;點選進入Project Property&lt;/li&gt;
&lt;li&gt;選擇 Project Property | Run/Debug Settings&lt;/li&gt;
&lt;li&gt;Edit你的Configurations，如果沒有的話，就New一個新的出來吧&lt;/li&gt;
&lt;li&gt;進入 Edit Configurations | Environment&lt;/li&gt;
&lt;li&gt;New &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;PATH &lt;/span&gt;&lt;/b&gt;:= &quot;&lt;u&gt;Step 2&lt;/u&gt;&quot;解壓縮後的裡面的&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;libs&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;目錄&lt;/li&gt;
&lt;li&gt;New &lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;SIKULI_HOME &lt;/span&gt;&lt;/b&gt;:=&amp;nbsp;&quot;&lt;u&gt;Step 2&lt;/u&gt;&quot;解壓縮後的目錄&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
5. 下載 Sikuli-IDE source code&lt;/h2&gt;
到&lt;a href=&quot;https://github.com/RaiMan/SikuliX-IDE&quot;&gt;Sikuli-IDE github&lt;/a&gt;的網頁下載source code，可以選擇&lt;i&gt;ZIP打包下載&lt;/i&gt;或是用&lt;i&gt;git clone&lt;/i&gt;下來&lt;br /&gt;
將下載的source code加入至Eclipse的project裡&lt;br /&gt;
注意，Eclipse的source code root folder裡，要直接放&lt;i&gt;i18n, icons, org, scripts&lt;/i&gt;這些fodler才行&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
6. Compile Sikuli-IDE source code&lt;/h2&gt;
基本上，我是在Window上compile的，直接在Eclipse run的話會有error&lt;br /&gt;
需要將下列的一些檔案加入Exclusion list裡(&lt;a href=&quot;http://stackoverflow.com/questions/8761504/skip-some-file-during-compilation-eclipse&quot;&gt;如何將檔案加入Exclusion list&lt;/a&gt;)&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;org.sikuli.ide.NativeLayerForMac.java&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;org.sikuli.ide.z_notused.EditorDocument.java&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;org.sikuli.ide.z_notused.EditorView.java&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
最後，按下&lt;b&gt;Run As Java Application&lt;/b&gt;，應該就可以看到Sikuli-IDE了!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghD-MEO4NX9VSB0nMcfYU-5tZlqIvyp9zxZsEq_WMihtHp3ZTZXepTrgVq__C1MlFw9csjN1fgWoQ2wdalkvXNmTBN2j8ke2O6WCNf-zU-YNLbK7TXvR0Syk-EGRqA2y8EW2ifJv7hVEly/s1600/SikuliIDE.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;191&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghD-MEO4NX9VSB0nMcfYU-5tZlqIvyp9zxZsEq_WMihtHp3ZTZXepTrgVq__C1MlFw9csjN1fgWoQ2wdalkvXNmTBN2j8ke2O6WCNf-zU-YNLbK7TXvR0Syk-EGRqA2y8EW2ifJv7hVEly/s320/SikuliIDE.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Run起來的結果畫面，看到這個，代表就成功了!&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Reference :&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;github - &lt;a href=&quot;https://github.com/RaiMan/SikuliX-IDE&quot;&gt;Sikuli-IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;github - &lt;a href=&quot;https://github.com/RaiMan/SikuliX-API&quot;&gt;Sikuli-API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sikuli-IDE Wiki -&amp;nbsp;&lt;a href=&quot;https://github.com/RaiMan/SikuliX-API/wiki/Usage-in-Java-programming&quot;&gt;Using sikuli-script.jar in Java programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sikuli - &lt;a href=&quot;http://doc.sikuli.org/contributing.html&quot;&gt;How to get involved&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sikuli -&amp;nbsp;&lt;a href=&quot;https://launchpad.net/sikuli/+download&quot;&gt;Download Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/06/sikuli-compile-ide-source-code-eclipse.html</link><author>noreply@blogger.com (Falldog)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghD-MEO4NX9VSB0nMcfYU-5tZlqIvyp9zxZsEq_WMihtHp3ZTZXepTrgVq__C1MlFw9csjN1fgWoQ2wdalkvXNmTBN2j8ke2O6WCNf-zU-YNLbK7TXvR0Syk-EGRqA2y8EW2ifJv7hVEly/s72-c/SikuliIDE.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-683945064663675567</guid><pubDate>Sat, 25 May 2013 02:57:00 +0000</pubDate><atom:updated>2015-01-05T09:59:17.454+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Assembly</category><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">Visual Studio</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><title>[C/C++] 研究long long * float overflow 可能導致的誤差</title><description>最近看bug看到一個奇怪的現象，在64bit的AP執行時，long long * float會有誤差出現，但是32bit的AP卻沒有這樣子的問題出現，直覺上不是應該32bit的AP比較會有問題嗎!?&lt;br /&gt;
&lt;br /&gt;
先來看一下 long long 跟 float ，long long的size是8個byte，float的size是4個byte&lt;br /&gt;
long long * float，compiler會將結果存到float的temp變數裡，此時誤差就可能會出現了，但是這個誤差是「有條件」地出現，並不是任何long long的數字乘上float都會產生誤差的&lt;br /&gt;
&lt;br /&gt;
以一個簡單的程式來驗證是否會產生誤差&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;bool check_longlong(long long v1)
{
    float f = 1.0f;
    long long v2 = long long( v1 * f );
    printf(&quot;ori value=%lld, new value=%lld, ori==new=%d&quot;, v1, v2, v1==v2);
    return v1==v2;
}

int _tmain(int argc, _TCHAR* argv[])
{
    check_longlong(0xF0000000000);//true - OK
    check_longlong(0x0FFFFFFFFFF);//false - Error!
    check_longlong(0x0FFFFFF);//true - OK
    check_longlong(0x1FFFFFF);//false - Error!
    return 0;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Float&lt;/h2&gt;
研究一下float的binary data的組成....&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/d/d2/Float_example.svg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/d/d2/Float_example.svg&quot; height=&quot;50&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Reference from Wiki&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://upload.wikimedia.org/math/b/1/8/b1822e3e8515bc84d1bcff1c3fa59903.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://upload.wikimedia.org/math/b/1/8/b1822e3e8515bc84d1bcff1c3fa59903.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Reference from Wiki&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;b&gt;sign&lt;/b&gt; ：1 bit - 表示正/負數&lt;br /&gt;
&lt;b&gt;exponent &lt;/b&gt;：8 bit - 表示fraction的2次方值&lt;br /&gt;
&lt;b&gt;fraction &lt;/b&gt;： 23 bit - 表示正規化後的數值(實際上可表示&lt;span style=&quot;color: #cc0000;&quot;&gt;24bit&lt;/span&gt;，因為小數點前永遠為1)&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.blogger.com/&quot;&gt;&lt;/a&gt;&lt;span id=&quot;goog_1638901462&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_1638901463&quot;&gt;&lt;/span&gt;由這示意圖可以發現，float的精準度就靠fraction的23bit(可表達24bit的數字)，因此，理論上只要與float相乘的數字binary值，第一個1跟最後一個1相差超過24的話，即會overflow產生誤差，不管是乘以long long(64bit) or int(32bit)，因為float最多就只能表達24bit的數字，你硬要塞25bit以上的數字，肯定會被crop或round掉的。所以，並不是數字太大就會有問題，而且前後的1相差超過float能表示的範圍才會有問題。&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
範例：&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x0FFFFFF = (0000&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;1111111111111111111111&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;font-size: xx-small;&quot;&gt;2&lt;/span&gt;&amp;nbsp;- OK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x1FFFFFF = (000&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;11111111111111111111111&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;font-size: xx-small;&quot;&gt;2&lt;/span&gt; - Error&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x2FFFFFF = (00&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;011111111111111111111111&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;font-size: xx-small;&quot;&gt;2&lt;/span&gt; - OK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x1000001 = (000&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;00000000000000000000000&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;font-size: xx-small;&quot;&gt;2&lt;/span&gt; - Error&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0xFFFFFF0 = (&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;1111111111111111111111&lt;span style=&quot;color: #cc0000;&quot;&gt;1&lt;/span&gt;0000)&lt;span style=&quot;font-size: xx-small;&quot;&gt;2&lt;/span&gt; - OK&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;注意上面紅色的1，代表第一個1與最後一個1&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;
Double&lt;/h2&gt;
同樣的道理，來看看double需要多大的值才會產生誤差呢&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/IEEE_754_Double_Floating_Point_Format.svg/618px-IEEE_754_Double_Floating_Point_Format.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/IEEE_754_Double_Floating_Point_Format.svg/618px-IEEE_754_Double_Floating_Point_Format.svg.png&quot; height=&quot;80&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Reference from Wiki&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;b&gt;fraction &lt;/b&gt;： 52bit (實際上可表示&lt;span style=&quot;color: #cc0000;&quot;&gt;53bit&lt;/span&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x1FFFFFFFFFFFFF = &amp;nbsp;9,007,199,254,740,991L - OK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x2FFFFFFFFFFFFF = 13,510,798,882,111,487L - Error&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x10000000000001 = &amp;nbsp;4,503,599,627,370,497L - OK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;0x20000000000001 = &amp;nbsp;9,007,199,254,740,993L - Error&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
著實是非常大的數字.... =_=&quot;&quot;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
Windows 32bit 沒誤差!?&lt;strike&gt;(安全下莊)&lt;/strike&gt;&lt;/h2&gt;
&lt;div&gt;
同樣的一套邏輯，在Windows 32bit, 64bit的AP卻有不一樣的結果，64bit會產生誤差，32bit卻不會產生誤差，why!? 用VisualStudio 2005與2008試了以後是一樣的結果，看了一下assembly code，x86與x64的指令是不一樣的，這應該就是產生不一樣結果的徵結點吧。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
看一下VC compile出來的x64 assembly code：&lt;br /&gt;
用SIMD的&lt;i&gt;cvtsi2ss&lt;/i&gt;先將longlong轉成float，相乘後，再用&lt;i&gt;cvttss2si&lt;/i&gt;轉回longlong的值，這標準的longlong與float轉換，就會產生誤差！&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
x64 assembly code&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; float f = 1.0f;
0000000140001043  movss       xmm0,dword ptr [__real@3f800000 (1400057C0h)] 
000000014000104B  movss       dword ptr [f],xmm0 
 long long v2 = long long(v1 * f);
0000000140001051  cvtsi2ss    xmm0,qword ptr [v1] 
0000000140001058  mulss       xmm0,dword ptr [f] 
000000014000105E  cvttss2si   rax,xmm0 
0000000140001063  mov         qword ptr [v2],rax 
&lt;/pre&gt;
&lt;br /&gt;
再看一下VC compile出來的x86的assembly code：&lt;br /&gt;
x86用&lt;i&gt;fild&lt;/i&gt;和&lt;i&gt;fmul&lt;/i&gt;做floating point的運算，最後再以&lt;i&gt;ftol2&lt;/i&gt;將float轉成long long，看了一下說明，&lt;i&gt;fild&lt;/i&gt;會將integer(16, 32, 64bit)轉成&lt;b&gt;80bit&lt;/b&gt; extension precision的float值，擁有80bit的precision乘完後的結果，直接轉成long long，當然不會有誤差囉！&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
x86 assembly code&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; float f = 1.0f;
0041140E  fld1             
00411410  fstp        dword ptr [f] 
 long long v2 = long long(v1 * f);
00411413  fild        qword ptr [v1] 
00411416  fmul        dword ptr [f] 
00411419  call        @ILT+435(__ftol2) (4111B8h) 
0041141E  mov         dword ptr [v2],eax 
00411421  mov         dword ptr [ebp-14h],edx 
&lt;/pre&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://babbage.cs.qc.cuny.edu/IEEE-754/index.xhtml&quot;&gt;IEEE 754 - float analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Single-precision_floating-point_format&quot;&gt;Wiki - Single precision floating point&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Double-precision_floating-point_format&quot;&gt;Wiki - Double precision floating point&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH14/CH14-4.html#HEADING4-37&quot;&gt;FILD, FMUL instruction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://courses.engr.illinois.edu/ece390/books/labmanual/inst-ref-simd.html&quot;&gt;SIMD - cvtsi2ss, cvttss2si instruction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/05/cc-long-long-multiply-float-overflow.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-4470325881253643375</guid><pubDate>Fri, 24 May 2013 08:21:00 +0000</pubDate><atom:updated>2015-01-14T18:03:23.164+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">DLL</category><title>[C/C++] 使用STL時，混用Debug &amp; Release Mode的DLL or LIB可能會造成 Crash!</title><description>當你的Release mode的EXE，使用Debug mode的DLL，中間如果有操作(new/delete)STL的container，很容易讓AP crash，包括下列的error ...&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Debug Assertion Failed&lt;/li&gt;
&lt;li&gt;_BLOCK_TYPE_IS_VALID&lt;/li&gt;
&lt;li&gt;_CrtIsValidHeapPointer&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
主要是因為build Debug mode的DLL，STL會enable _SECURE_SEL 和 _HAS_ITERATOR_DEBUGGING，裡面會對memory多做一些checking，假如你在Release mode，new了一塊memory後放到Debug mode的STL container，在Debug mode裡試著去delete這塊memory時，會多做一些Release mode不會做的error checking，就會有不預期的exception出現。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
想想，Release跟Debug所用的CRunTime library是不一樣的，同一塊memory讓不一樣的CRunTime處理，當然可能會出錯。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;解決辦法：&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;(&lt;b&gt;不混用&lt;/b&gt;) 將全部的module統一build成Release or Debug mode&lt;/li&gt;
&lt;li&gt;(&lt;b&gt;大統一&lt;/b&gt;) Memory allocated/free的行為，統一交給一個module處理&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Sample Error Code :&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;////////////////////////////////////////////////////////
// A.dll - build in Release mode
////////////////////////////////////////////////////////
B bMgr;
void AppendIntArray(int* array, int size)
{
    for(int i=0 ; i&amp;lt;size ; ++i)
    {
        // New memeory in A.dll (Release Mode)
        bMgr.m_int.push_back(new Value&amp;lt;int&amp;gt;(array[i])); 
    }
}
void AppendFloatArray(float* array, int size)
{
    for(int i=0 ; i&amp;lt;size ; ++i)
    {
        // New memeory in A.dll (Release Mode)
        bMgr.m_float.push_back(new Value&amp;lt;float&amp;gt;(array[i]));
    }
}


////////////////////////////////////////////////////////
// B.dll - build in Debug mode
////////////////////////////////////////////////////////
template &amp;lt;typename T&amp;gt;
class Value
{
public:
    Value(T _v){v=_v;}
    T v;
}

class B
{
public:
    void ClearAll();
    vector&amp;lt; Value&amp;lt;int&amp;gt;* &amp;gt; m_int;
    vector&amp;lt; Value&amp;lt;float&amp;gt;* &amp;gt; m_float;
}

void B::ClearAll()
{
    // Release memeory in B.dll (Debug Mode)
    for(int i=0 ; i&amp;lt;m_int.size() ; ++i)
        delete m_int[i];
    m_int.clear();
    
    // Release memeory in B.dll (Debug Mode)
    for(int i=0 ; i&amp;lt;m_float.size() ; ++i)
        delete m_float[i];
    m_float.clear();
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Reference&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;MSDN thread - &lt;a href=&quot;http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/3072753b-caa5-4894-bb26-1b85914e27ab/&quot;&gt;Debug assertion failed when deleting array allocated in DLL in Debug Mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://choorucode.com/2010/09/10/visual-c-iterator-checks-and-slow-stl-code/&quot;&gt;Visual C++ - Iterator check and Slow STL code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2013/05/cc-stl-debug-release-modedll-or-lib.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-8262014462739143774</guid><pubDate>Fri, 24 May 2013 03:07:00 +0000</pubDate><atom:updated>2013-05-24T11:07:07.898+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Python</category><category domain="http://www.blogger.com/atom/ns#">Sikuli</category><title>[Python] 為Python2.5 unittest 加上setUpClass &amp; tearDownClass 的功能</title><description>最近使用 &lt;b&gt;&lt;i&gt;Sikuli&lt;/i&gt;&lt;/b&gt; 替Project作AutoTest的功能，以Python的unittest為架構下去撰寫，發現有些綁手綁腳的地方，因為Sikuli是使用&lt;b&gt;Jython 2.5&lt;/b&gt;，連帶的unittest也止於Python 2.5的版本。由於測試的項目眾多，需要撰寫多個TestCase，所以&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;setUpClass&lt;/span&gt;&lt;/b&gt;與&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;tearDownClass&lt;/span&gt;&lt;/b&gt;更顯得重要，可以為每個TestCase做pre-process與post-process。偏偏setUpClass與tearDownClass是在Python 2.7後才支援的，所以想在Sikuli裡套用的話，必須自己加一些Code才行了。&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
說明一下，TestCase裡的setUp與tearDown是TestCase裡的每一個 test function 的pre-processing &amp;amp; post-processing，而setUpClass與tearDownClass是&lt;b&gt;整個TestCase&lt;/b&gt;被run起來的pre-processing &amp;amp; post-processing。&lt;br /&gt;
&lt;br /&gt;
以下的sample code，主要就是繼承TestSuite，定義一個自己的MyTestSuite，override run()，讓它試著去執行setUpClass與tearDownClass。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;import unittest
import traceback
class MyTestSuite(unittest.TestSuite):
    # sikuli jython 2.5 unittest doesn&#39;t have setUpClass &amp;amp; tearDownClass
    # Add the class to support this feature
    def __init__(self,*argv,**argd):
        unittest.TestSuite.__init__(self, *argv, **argd)
    
    def run(self, result):
        sample = self._tests[0] if len(self._tests)&amp;gt;0 else None
        if sample and hasattr(sample, &#39;setUpClass&#39;):
            try:
                sample.setUpClass()
            except:
                traceback.print_exc()
        
        for test in self._tests:
            if result.shouldStop:
                break
            test(result)
            
        if sample and hasattr(sample, &#39;tearDownClass&#39;):
            try:
                sample.tearDownClass()
            except:
                traceback.print_exc()
        return result

class MyTestCase(unittest.TestCase):
    def setUpClass(self):
        print &#39;MyTestCase::setUpClass&#39;
    def tearDownClass(self):
        print &#39;MyTestCase::tearDownClass&#39;
    def test_MyTest1(self):
        print &#39;MyTestCase::MyTest1&#39;
    def test_MyTest2(self):
        print &#39;MyTestCase::MyTest2&#39;

if __name__ == &#39;__main__&#39;:
    suites = unittest.TestSuite([unittest.makeSuite(MyTestCase, suiteClass=MyTestSuite)])
    runner = unittest.TextTestRunner()
    runner.run(suites)
    # output result sequence ...
    #&amp;gt;&amp;gt;&amp;gt; MyTestCase::setUpClass
    #&amp;gt;&amp;gt;&amp;gt; MyTestCase::MyTest1
    #&amp;gt;&amp;gt;&amp;gt; MyTestCase::MyTest2
    #&amp;gt;&amp;gt;&amp;gt; MyTestCase::tearDownClass
&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sikuli.org/&quot;&gt;Sikuli官網&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.python.org/2/library/unittest.html&quot;&gt;Python 2 - unittest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/05/python-python25-unittest-setupclass.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-6025596962263768334</guid><pubDate>Thu, 23 May 2013 09:46:00 +0000</pubDate><atom:updated>2015-01-14T18:03:05.472+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><category domain="http://www.blogger.com/atom/ns#">DLL</category><category domain="http://www.blogger.com/atom/ns#">Win32</category><title>[C/C++] 取得LIB目前的DLL module path</title><description>如果寫了一個LIB or Cpp檔，讓多個DLL module include使用，該如果拿到目前DLL的module path?&lt;br /&gt;
&lt;br /&gt;
GetModuleFileName() 參數hModule傳NULL的話，只能知道執行檔exe的路徑&lt;br /&gt;
要想知道自己在哪個DLL module的話，必須埋一些code才行&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;EXTERN_C IMAGE_DOS_HEADER __ImageBase
//...
WCHAR dll_path[MAX_PATH] = {0};
GetModuleFileNameW((HINSTANCE)&amp;amp;__ImageBase, dll_path, _MAX_PATH);
&lt;/pre&gt;
&lt;br /&gt;
Reference :&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;StackOverflow - &lt;a href=&quot;http://stackoverflow.com/questions/6924195/get-dll-path-at-runtime&quot;&gt;Get Dll path at runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MSDN - &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v=vs.85).aspx&quot;&gt;GetModuleFileName()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description><link>http://falldog7.blogspot.com/2013/05/cc-lib-dll-module-path.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-5817647334262996203.post-4810407961404108786</guid><pubDate>Fri, 22 Mar 2013 08:26:00 +0000</pubDate><atom:updated>2014-09-13T12:01:33.057+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/Cpp</category><title>[C/C++] General pointer type for support x86 &amp; x64</title><description>一個pointer的size在x86跟x64的環境裡是不一樣大的&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;x86&#39;s pointer size = 4 bytes&lt;/li&gt;
&lt;li&gt;x64&#39;s pointer size = 8 bytes&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
如果你在程式中用int or long去儲存一個pointer的話，可能在compile成x86可以work，但是compile成x64執行的話，可能就會exception了&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
所以建議是用標準的&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #cc0000;&quot;&gt;uintptr_t &lt;/span&gt;/ &lt;span style=&quot;color: #cc0000;&quot;&gt;intptr_t&amp;nbsp;&lt;/span&gt;&lt;/b&gt;去儲存pointer，uintptr_t在copmpile成x86時的size是4 bytes，x64是8 bytes，它在C++11時才被列入標準，但在大部分的C++03的compiler已經支援了&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
include header : &lt;span style=&quot;color: #38761d;&quot;&gt;&amp;lt;cstdint&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Reference :&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/1845482/what-is-uintptr-t-data-type&quot;&gt;StackOverflow - What is unitptr_t?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cplusplus.com/reference/cstdint/&quot;&gt;cplusplus - cstdint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><link>http://falldog7.blogspot.com/2013/03/cc-general-pointer-type-for-support-x86.html</link><author>noreply@blogger.com (Falldog)</author><thr:total>0</thr:total></item></channel></rss>