<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>浏忙大爆炸 &#187; 技术</title>
	<atom:link href="http://blog.waterlin.org/articles/category/%e6%8a%80%e6%9c%af/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.waterlin.org</link>
	<description>源于理工科男的烂笔头情结</description>
	<lastBuildDate>Fri, 03 Feb 2012 08:35:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>C# 引用 C++ 链接库</title>
		<link>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html</link>
		<comments>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 08:35:37 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html</guid>
		<description><![CDATA[最近在尝试用新的方式来写一个新的 Windows 客户端，当作练习。主要是用 C++ 把复杂的算法写成链接库，然后用 C# 做界面前端，从 C# 调用用 C++ 写好的非托管代码。 尝试通过这种方式解决两个问题： C# 的计算效率问题，虽然从各种资料来看，好像 C# 的托管代码对效率的影响并没有想象的夸张，但不管怎么样，有些东西用 C++ 写就是方便一些； 用 C++ 可以方便地链接现有的代码库、算法库。 其实，这种架构可以看成是一种 C/S 架构的简化版，但是省去了 Socket 通信这一层。 我采用的是最简单的 P/Invokes 的方式来实现 C# 调用 C++ 链接库，详细的教程，可以看一下 Using dumpbin.exe as an Aid for Declaring P/Invokes 这篇文章。 这里先简单说说两点和代码无关的问题 如果 C++ 链接库的计算很耗时，一定要在 C# 客户端里开一个线程来处理，否则容易造成死机，这和 MFC 之类的原理一样。 为了测试你从 C# 链接 C++ 链接库是否成功，可以用 [...]]]></description>
			<content:encoded><![CDATA[<p>最近在尝试用新的方式来写一个新的 Windows 客户端，当作练习。主要是<a href="http://cn.waterlin.org/Microsoft/visual-studio-dll-project.html">用 C++ 把复杂的算法写成链接库</a>，然后用 C# 做界面前端，从 C# 调用用 C++ 写好的非托管代码。</p>
<p>尝试通过这种方式解决两个问题：</p>
<ol>
<li>C# 的计算效率问题，虽然从各种资料来看，好像 C# 的托管代码对效率的影响并没有想象的夸张，但不管怎么样，有些东西用 C++ 写就是方便一些；</li>
<li>用 C++ 可以方便地链接现有的代码库、算法库。</li>
</ol>
<p>其实，这种架构可以看成是一种 C/S 架构的简化版，但是省去了 Socket 通信这一层。</p>
<p>我采用的是最简单的 P/Invokes 的方式来实现 C# 调用 C++ 链接库，详细的教程，可以看一下 <a href="http://msdn.microsoft.com/en-us/library/aa446532.aspx">Using dumpbin.exe as an Aid for Declaring P/Invokes</a> 这篇文章。</p>
<div class="outline-3">
<h3 id="sec-1.1">这里先简单说说两点和代码无关的问题</h3>
<div class="outline-text-3">
<ol>
<li>如果 C++ 链接库的计算很耗时，一定要在 C# 客户端里开一个线程来处理，否则容易造成死机，这和 MFC 之类的原理一样。</li>
<li>为了测试你从 C# 链接 C++ 链接库是否成功，可以用 C# 新建一个命令行工程专门测试，用这种方式来测试更加直接与有效。</li>
</ol></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.2">再谈几点有关技术实现细节的问题，也是我折腾了很久的困惑之处</h3>
<div class="outline-text-3">
<div class="outline-4">
<h4 id="sec-1.2.1">1. 有关 C++ 链接库 EntryPoint 的名称</h4>
<div class="outline-text-4">
<p>我在刚开始从 C# 里链接 C++ 链接库的 API 时，想当然地以为就是函数名称。但是这样操作无论如何也调用不成功，<a href="http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx#pinvoke_callingdllexport">需要在 C++ 链接库里添加一个 extern 关键字</a>，否则链接库编译出来的 API 名称，是混淆过的，不方便你在 C# 里作为 EntryPoint 来书写。</p>
<p>比如说，有如下 C++ 链接库的 API 函数（建议链接库给外面调用的 API 最好用 C 风格来实现，方便减少头文件依赖关系）：</p>
<pre>
<span>extern</span> <span>"C"</span> <span>__declspec</span>(dllexport) <span>bool</span> <span>Function1</span>(<span>const</span> <span>char</span>* <span>param1</span>,
                                                <span>const</span> <span>char</span>* <span>param2</span>,
                                                <span>const</span> <span>char</span>* <span>param3</span>);
</pre>
<p>翻译成 C# 函数则如下：</p>
<pre>
[DllImport(<span>"Example.dll"</span>, EntryPoint = <span>"Function1"</span>, ExactSpelling = <span>false</span>]
[<span>return</span>: MarshalAs(UnmanagedType.U1)]
<span>public</span> <span>static</span> <span>extern</span> <span>bool</span> Function1([MarshalAs(UnmanagedType.LPStr)] String param1,
                                    [MarshalAs(UnmanagedType.LPStr)] String param2,
                                    [MarshalAs(UnmanagedType.LPStr)] String param3);
</pre>
<p>这里注意，找 EntryPoint 一定要准确，否则不容易找到。为了明确地找到 API 函数的 EntryPoint 名称，可以使用 Dumpbin.exe 工具。</p>
<p>dumpbin.exe 工具默认在以下目录：</p>
<pre>
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin
</pre>
<p>如果从这个目录里运行 dumpbin.exe 会提示找不到动态链接库 mspdb80.dll 的错误，可以把 dumpbin.exe 拷贝到目录</p>
<pre>
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE
</pre>
<p>，并从这个目录下运行 dumpbin.exe 来解决这个问题。</p>
<p>运行命令</p>
<pre>
dumpbin.exe /EXPORTS dllname.dll
</pre>
<p>后，你会看到很多 ? @ 混合在一起的名称，所以，为了使你在 C# 里的代码可读性比较强，需要改造这些名称。在链接库里，我们可以通过用 extern 关键字来标明，这样生成的链接库 EntryPoint 依然会是原始的名称。</p>
</p></div>
</p></div>
<div class="outline-4">
<h4 id="sec-1.2.2">2. C# 程序运行时提示说找不到链接库</h4>
<div class="outline-text-4">
<p>如果按上述方法编写好了代码，一运行 C# 程序却提示说：</p>
<pre>
未处理的"System.DllNotFoundException"类型的异常出现在 example.exe 中。

其他信息: 无法加载 DLL"cppexample.dll": 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
</pre>
<p>这个时候，你需要找一找你的 dll 是否在可执行目录下，或是你写的 dll 是否依赖于其它第三方dll，一定要确保所有的 dll 都能顺利被找到。</p>
</p></div>
</p></div>
<div class="outline-4">
<h4 id="sec-1.2.3">3. 参数的映射办法</h4>
<div class="outline-text-4">
<p>你的函数肯定有若干个参数，那这些参数应该和 C# 里的类型如何一一对应呢？在 C# 里，<a href="http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx#pinvoke_defaultmarshaling">这种映射关系叫做 marshal</a>。</p>
<p>类型映射，需要仔细检查一下手册，比如说，const char* 就应该这样映射：</p>
<pre>
[MarshalAs(UnmanagedType.LPStr)]
</pre>
<p><a href="http://msdn.microsoft.com/en-us/library/2x8kf7zx(v=vs.80).aspx">Using C++ Interop</a> 文章的未尾，有列出一大串的类型映射列表。</p>
</p></div>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.3">小结</h3>
<div class="outline-text-3">
<p>初步用 C# 来写界面，感觉更方便、快速，起码比 MFC 来得简单、直接；从 C# 里直接调用 C++ 链接库，也很方便。但这两者结合起来写应用，稳定性还有待进一步测试。</p>
</p></div>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/link-cpp-dll-from-csharp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C/C++ 多线程参数需要尽量采用动态分配的方式来分配</title>
		<link>http://blog.waterlin.org/articles/cpp-multi-thread-passing-params-problems.html</link>
		<comments>http://blog.waterlin.org/articles/cpp-multi-thread-passing-params-problems.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 06:40:00 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/cpp-multi-thread-passing-params-problems.html</guid>
		<description><![CDATA[在 C/C++ 多线程编程下，如果不注意，采用普通变量传递参数值给线程会有一些误区，需要特别小心。 下面浏忙绪绪就举两个例子来说明一下。 char* 参数在多线程下出现的怪异现象 最近在用 Boost 库写多线程程序时，需要启动若干个线程，这些线程分别处理不同的事情，线程会获取一个字符串参数，用来标识内容。在编写代码的时候，出现了一个很怪异的现象，例子代码如下： const int tNum = 4;//并发线程数 vector&#60;boost::thread*&#62; tBox; for (int i=0; i &#60; tNum; i++ ) { char strThread[20]; sprintf(strThread, "thread%d",i); //strThread 字符串是传入的 const char* 类型 boost::thread* thread_0 = new boost::thread( StreamProcesser, param1, param2, strThread); tBox.push_back(thread_0); boost::xtime xt; boost::xtime_get(&#38;xt, boost::TIME_UTC); xt.sec += 2; boost::thread::sleep(xt); } for (int [...]]]></description>
			<content:encoded><![CDATA[<p>在 C/C++ 多线程编程下，如果不注意，采用普通变量传递参数值给线程会有一些误区，需要特别小心。</p>
<p>下面<a href="http://blog.waterlin.org">浏忙绪绪</a>就举两个例子来说明一下。</p>
<div class="outline-3">
<h3 id="sec-1.1">char* 参数在多线程下出现的怪异现象</h3>
<div class="outline-text-3">
<p>最近在用 <a href="http://blog.waterlin.org/articles/compile-and-install-boost-under-cygwin.html">Boost 库</a>写多线程程序时，需要启动若干个线程，这些线程分别处理不同的事情，线程会获取一个字符串参数，用来标识内容。在编写代码的时候，出现了一个很怪异的现象，例子代码如下：</p>
<pre>
<span>const</span> <span>int</span> <span>tNum</span> = 4;<span>//</span><span>并发线程数
</span><span>vector</span>&lt;<span>boost</span>::<span>thread</span>*&gt; <span>tBox</span>;

<span>for</span> (<span>int</span> <span>i</span>=0; i &lt; tNum; i++ )
{
    <span>char</span> <span>strThread</span>[20];
    sprintf(strThread, <span>"thread%d"</span>,i);
    <span>//</span><span>strThread 字符串是传入的 const char* 类型
</span>    <span>boost</span>::<span>thread</span>* <span>thread_0</span> = <span>new</span> <span>boost</span>::<span>thread</span>( StreamProcesser,
                                                 param1,
                                                 param2,
                                                 strThread);

    tBox.push_back(thread_0);

    <span>boost</span>::<span>xtime</span> <span>xt</span>;
    <span>boost</span>::xtime_get(&amp;xt, <span>boost</span>::TIME_UTC);
    xt.sec += 2;
    <span>boost</span>::<span>thread</span>::sleep(xt);
}

<span>for</span> (<span>int</span> <span>i</span>=0; i &lt; tNum; i++ )
{
    <span>boost</span>::<span>thread</span>* <span>thread_0</span> = tBox[i];
    thread_0-&gt;join();
    <span>delete</span> thread_0;
}
</pre>
<p>在线程函数启动参数中，有一个参数是 const char* 类型。如果我在线程中，没有先对 char 字符串拷贝一个副本，则当4个线程都跑起来后，再去读取这个参数，很有可能会读到同一个字符串。</p>
<p>这是因为编译器把 strThread 的地址编码为同一个内存地址造成的，所以，所有的线程读取的都是最后一次设置 strThread 的值。</p>
<p>结论：</p>
<ol>
<li>传入 char* 后，一定要对 char 字符串拷贝一个副本，否则这个指针指向的内容很有可能被改变；</li>
<li>多用 C++ 的 string，少用 char 或是 char*，用值拷贝的方式比单纯传递一个指针要更安全；</li>
<li>最安全的做法，应该是动态分配一个空间，用来保存传递给线程的参数值，在线程结束后再销毁该值。</li>
</ol></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.2">int 参数在多线程下被重复赋值的怪异现象</h3>
<div class="outline-text-3">
<p>同样，如果传入参数是整型或是其它类型的时候，也会有上述类似的问题。<a href="http://cn.waterlin.org/Microsoft/Visual-studio-unusual.html">拿 Win32 的 CreateThread 函数</a>来说，同样需要保证传入的参数不被修改，例如下面的代码就非常危险：</p>
<pre>
DWORD <span>WINAPI</span> <span>CloseThreadFun</span>( <span>LPVOID</span> <span>param</span>)
{
    <span>int</span>* <span>pHandle</span> = (<span>int</span>*)param;
    <span>const</span> <span>int</span> <span>handle</span> = *pHandle;

    <span>//</span><span>打印句柄
</span>    printf(<span>"get handle is %d"</span>, handle);

    <span>return</span> 0;
}

<span>int</span> <span>_tmain</span>(<span>int</span> <span>argc</span>, <span>_TCHAR</span>* <span>argv</span>[])
{
    <span>const</span> <span>int</span> <span>THREAD_NUM</span> = 4;

    <span>HANDLE</span>* <span>lphandle</span> = <span>new</span> <span>HANDLE</span>[THREAD_NUM];
    <span>for</span> (<span>int</span> <span>j</span> = 0; j &lt; THREAD_NUM; j++)
    {
        <span>HANDLE</span> <span>hthread</span>;
        hthread = CreateThread(<span>NULL</span>, 0, CloseThreadFun, (<span>LPVOID</span>)&amp;j, 0, <span>NULL</span>);
        lphandle[j] = hthread;
    }

    WaitForMultipleObjects(THREAD_NUM, lphandle, TRUE, INFINITE);

    <span>delete</span> [] lphandle;

    <span>return</span> 0;
}
</pre>
<p>在调用 CloseThreadFun 来启动一个线程后，j 的值很有可能已经被修改掉了：线程启动总是需要时间的，而参数指针指向地址的内容，很有可能在此期间被修改了。比如，上面的代码，运行后，打印的内容如下：</p>
<pre>
get handle is 3
get handle is 4
get handle is 4
get handle is 4
</pre>
<p>这就说明了 j 值被重复修改后，会导致线程参数不对的现象。</p>
<p>解决办法：用一个 int 数组把需要传入到各个线程的参数缓存起来，尽量保证地址不一样。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.3">结论</h3>
<div class="outline-text-3">
<p>传入线程的参数，应该尽量采用动态分配内存的方式来生成。否则如果采用临时变量，则随着变量生命周期的消逝，该变量的指针，很有可能会变成一个毫无意义的指针（或是被新的值覆盖，或是被成为一个遗留数）。</p>
<p>采用动态分配的变量作为线程启动时的参数，在线程结束后再销毁这个动态分配的变量，则是一个安全法则。</p>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/cpp-multi-thread-passing-params-problems.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Log4Cxx 0.10.0 在 Linux 下退出程序时导致程序中断</title>
		<link>http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html</link>
		<comments>http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html#comments</comments>
		<pubDate>Tue, 17 Jan 2012 09:13:58 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html</guid>
		<description><![CDATA[最近在写 Linux 程序的时候，碰到这样的问题：Log4Cxx 0.10.0 在 Linux 下退出程序时导致程序中断，即提示出现 segmentation fault 错误。 如果你用 gdb 调试，会提示如下信息： Program received signal SIGSEGV, Segmentation fault. 0x02fa68f3 in apr_vformatter () from /usr/lib/libapr-1.so.0 原因是因为 Log4Cxx 在退出时有非法的资源释放。 有一个解决办法：可以在程序退出时，显示地关闭 Log4Cxx 对象。 I have the same problem if I use log4cxx.AsyncAppender. I fixed the problem by calling log4cxx::LogManager::shutdown(); before the end of the process. It's not [...]]]></description>
			<content:encoded><![CDATA[<p>最近在写 Linux 程序的时候，碰到这样的问题：<a href="http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html">Log4Cxx 0.10.0</a> 在 Linux 下退出程序时导致程序中断，即提示出现 segmentation fault 错误。</p>
<p>如果你用 gdb 调试，会提示如下信息：</p>
<pre>
Program received signal SIGSEGV, Segmentation fault.
0x02fa68f3 in apr_vformatter () from /usr/lib/libapr-1.so.0
</pre>
<p>原因是因为 <a href="http://blog.waterlin.org/articles/writing-cross-platform-cpp-code.html">Log4Cxx</a> 在退出时有非法的资源释放。</p>
<p>有一个解决办法：可以在程序退出时，显示地关闭 Log4Cxx 对象。</p>
<pre>
I have the same problem if I use log4cxx.AsyncAppender.
I fixed the problem by calling log4cxx::LogManager::shutdown(); before the end of the process.
It's not very clean but it works.
</pre>
<p>即<a href="http://comments.gmane.org/gmane.comp.apache.logging.log4cxx.user/2923">在程序退出时使用语句</a></p>
<pre>
log4cxx::LogManager::shutdown();
</pre>
<p>来清理 log4cxx，而不是让它自己来清理。</p>
<p>注意： <strong>需要在程序所有可能退出的地方，设置这一语句</strong> ，否则依然会有 segmentation fault 的问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>编写跨平台的 C++ 代码</title>
		<link>http://blog.waterlin.org/articles/writing-cross-platform-cpp-code.html</link>
		<comments>http://blog.waterlin.org/articles/writing-cross-platform-cpp-code.html#comments</comments>
		<pubDate>Tue, 27 Dec 2011 06:38:32 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/writing-cross-platform-cpp-code.html</guid>
		<description><![CDATA[最近都在写一些跨 Windows 和 Linux 平台的 C++ 代码，略有心得，整理成文，备忘一下。 有关预编译指令 Visual Studio 会自动在源代码里添加 #pragma once 这个指令，在 Linux Gcc 编译器下应该怎么样处理类似的情况呢？ 维基百科上有一个权威说法： http://en.wikipedia.org/wiki/Pragma_once 所以，在编写跨平台的 C++ 代码时，最好使用下面这种方式来获得跨平台的特性： #pragma once #ifndef GRANDFATHER_H #define GRANDFATHER_H struct foo { int member; }; #endif /* GRANDFATHER_H */ 有关链接库工程的跨平台 Windows 下使用 __declspec(dllexport) 来标明一个动态链接库的函数接口，而在 Linux 下，则完全没有这个必要。 这个时候，如果动态链接库代码需要跨平台，应该怎么处理呢？ 你可以用如下宏来进行区分： #ifdef WIN32 #define EXPORT_XX __declspec(dllexport) #else #define EXPORT_XX [...]]]></description>
			<content:encoded><![CDATA[<p>最近都在写一些跨 Windows 和 Linux 平台的 C++ 代码，略有心得，整理成文，备忘一下。</p>
<div class="outline-3">
<h3 id="sec-1.1">有关预编译指令</h3>
<div class="outline-text-3">
<p>Visual Studio 会自动在源代码里添加</p>
<pre>
#pragma once
</pre>
<p>这个指令，在 Linux Gcc 编译器下应该怎么样处理类似的情况呢？</p>
<p><a href="http://en.wikipedia.org/wiki/Pragma_once">维基百科</a>上有一个权威说法：</p>
<pre>

http://en.wikipedia.org/wiki/Pragma_once
</pre>
<p>所以，在编写跨平台的 C++ 代码时，最好使用下面这种方式来获得跨平台的特性：</p>
<pre>
<span>#pragma</span> once
<span>#if</span><span>n</span><span>def</span> GRANDFATHER_H
<span>#define</span> <span>GRANDFATHER_H</span>

<span>struct</span> <span>foo</span>
{
    <span>int</span> <span>member</span>;
};

<span>#endif</span> <span>/* </span><span>GRANDFATHER_H */</span>
</pre>
</div></div>
<div class="outline-3">
<h3 id="sec-1.2">有关链接库工程的跨平台</h3>
<div class="outline-text-3">
<p><a href="http://cn.waterlin.org/Microsoft/visual-studio-dll-project.html">Windows 下使用 __declspec(dllexport) 来标明一个动态链接库的函数接口</a>，而在 Linux 下，则完全没有这个必要。</p>
<p>这个时候，如果动态链接库代码需要跨平台，应该怎么处理呢？</p>
<p>你可以用如下宏来进行区分：</p>
<pre>
<span>#ifdef</span> WIN32
<span>#define</span> <span>EXPORT_XX</span> <span>__declspec</span>(dllexport)
<span>#else</span>
<span>#define</span> <span>EXPORT_XX</span>
<span>#endif</span>
</pre>
</div></div>
<div class="outline-3">
<h3 id="sec-1.3">源代码的编码格式</h3>
<div class="outline-text-3">
<p>源代码的编码格式，最好统一用 GBK 或是 UTF-8，以避免不同编码器之间转换造成的乱码。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.4">注意代码里的文件名大小写。</h3>
<div class="outline-text-3">
<p>Windows 里 include 一个头文件，你的大小写可以随便写。但是在 Linux 上，你得小心了，clsssa.h 你不能写成</p>
<pre>
#include "ClassA.h"
</pre>
<p>因为在 Linux 上，文件及目录名是大小写敏感的。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.5">一些类型名称</h3>
<div class="outline-text-3">
<p>Windows 处理宽字符集与窄字符集采用的方法，是用宏定义来区分。比如说 TCHAR 在不同的工程下，属于不同的类型。</p>
<p>而在 Linux 下，则需要注意这些问题。为了让你的代码可移植性强。一定要少用 BOOL, TCHAR 这些类型，而要用原生态的 C/C++ 类型，比如说 bool, char 等。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.6">有关 _tmain 等主函数问题。</h3>
<div class="outline-text-3">
<p>默认情况下，Visual Studio 新建的 Win32 Console 工程，全是类似于这样的。</p>
<pre>
<span>int</span> <span>_tmain</span>(<span>int</span> <span>argc</span>, <span>_TCHAR</span>* <span>argv</span>[])
{
}
</pre>
<p>这些代码，移植到 Linux 下面，就需要我们自己做一部分工作。</p>
<p>如果你在 Visual Studio 用的是 Unicode 编码的，则对应的 Linux 代码应该是另外一套。我则是用宏裁剪了两个主函数出来。如果你有什么更好的方法，可以跟我分享。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.7">注意一些库在 Linux 和 Windows 平台下的不同表现</h3>
<div class="outline-text-3">
<p>虽然你的程序可能依赖大量的跨平台库，这些库号称是跨平台的，但是很有可能在不同的平台的表现，会有所不同。例如，<a href="http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html">log4cxx 在 Linux 和 Windows 下就会有字符集设置的差别</a>。</p>
<p>你在编写跨平台代码的时候，就应该特别小心这些库的细微差别，及时调整。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.8">后记</h3>
<div class="outline-text-3">
<p>以上是一些跨平台 C/C++ 代码编写的经验，备忘一下，也希望对大家有用。</p>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/writing-cross-platform-cpp-code.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>log4cxx0.10.0 版本在 Linux 无法输出中文的问题</title>
		<link>http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html</link>
		<comments>http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html#comments</comments>
		<pubDate>Wed, 14 Dec 2011 08:16:46 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html</guid>
		<description><![CDATA[最近在 Linux 下使用 log4cxx 库，使用的 log4cxx 版本为 0.10.0，结果无法显示中文日志信息。 这可怎么办呢？我不可能把中文日志全部一行一行替换为英文的，这可是一个非常傻B的举动。 经过研究，终于知道需要经过如下步骤才能让 log4cxx 在 Linux 下正常显示中文日志： 你可以先 locale 检查一下 Linux 终端环境是不是 zh_CN ； $ locale 如果你的是 en_US 之类的编码，则需要把 locale 设置为简体中文： $ export LC_ALL="zh_CN.UTF-8" 如果你的系统提示说没有安装本字符集，则需要用命令进行安装： $ sudo apt-get install language-pack-zh-hans 在程序里设置应用程序的 locale 和终端一样： LoggerPtr logger; log4cxx::PropertyConfigurator::configure("./log4cxx.properties"); logger= Logger::getLogger("test") ; logger-&#62;info(("Start logging")); setlocale(LC_ALL, "zh_CN.UTF-8"); 关键是最后这一句 setlocale，要设置得和终端一样，都是 zh_CN.UTF-8。 这样，你的程序就可以用 log4cxx0.10.0 [...]]]></description>
			<content:encoded><![CDATA[<p>最近在 Linux 下使用 log4cxx 库，使用的 log4cxx 版本为 0.10.0，结果无法显示中文日志信息。</p>
<p>这可怎么办呢？我不可能把中文日志全部一行一行替换为英文的，这可是一个非常傻B的举动。</p>
<p>经过研究，终于知道需要经过如下步骤才能让 log4cxx 在 Linux 下正常显示中文日志：</p>
<ol>
<li>你可以先 locale 检查一下 Linux 终端环境是不是 zh_CN ； </p>
<pre>
$ locale
</pre>
</li>
<li>如果你的是 en_US 之类的编码，则需要把 locale 设置为简体中文：
<pre>
$ export <span>LC_ALL</span>=<span>"zh_CN.UTF-8"</span>
</pre>
<p>如果你的系统提示说没有安装本字符集，则需要用命令进行安装：</p>
<pre>
$ sudo apt-get install language-pack-zh-hans
</pre>
</li>
<li>在程序里设置应用程序的 locale 和终端一样：
<pre>
LoggerPtr logger;
log4cxx::PropertyConfigurator::configure("./log4cxx.properties");
logger= Logger::getLogger("test") ;
logger-&gt;info(("Start logging"));
setlocale(LC_ALL, "zh_CN.UTF-8");
</pre>
<p>关键是最后这一句 setlocale，要设置得和终端一样，都是 zh_CN.UTF-8。</p>
</li>
</ol>
<p>这样，你的程序就可以用 log4cxx0.10.0 输出中文日志信息了。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/log-chinese-logs-on-linux-using-log4cxx.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ubuntu 11.10 下 OpenCV2.2 及更低版本无法读取视频的问题</title>
		<link>http://blog.waterlin.org/articles/ubuntu-opencv-read-video-problem.html</link>
		<comments>http://blog.waterlin.org/articles/ubuntu-opencv-read-video-problem.html#comments</comments>
		<pubDate>Fri, 25 Nov 2011 09:01:39 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/ubuntu-opencv-read-video-problem.html</guid>
		<description><![CDATA[今天在 Ubuntu 下使用 OpenCV 来读取一个视频，碰到了下述问题： 自己手动安装的 OpenCV2.2.0 无法正确读取视频内容，用函数 cvCaptureFromAVI() 及 cvGetCaptureProperty() 均提示说失败： 所有的测试视频在 Windows 下用 OpenCV2.2.0 是可以正常读取的，应该是 ffmpeg 安装不完全或是不正确。 从源里安装 OpenCV2.1 后，可以打开视频读取数据，可是在读取视频帧内容的时候，却提示如下错误： [swscaler @ 0x94b3e80]No accelerated colorspace conversion found from yuv420p to bgr24. 这个问题应该是 OpenCV 在用 ffmpeg 解压 yuv420 数据时出错。 对于上述问题，可以采用下面的办法来解决： 重新安装 ffmpeg x264：Install and use the latest FFmpeg and x264 再重新安装 OpenCV，经测试，可以正确安装 OpenCV 2.3.1 [...]]]></description>
			<content:encoded><![CDATA[<p>今天在 Ubuntu 下使用 OpenCV 来读取一个视频，碰到了下述问题：</p>
<ol>
<li>自己<a href="http://cn.waterlin.org/CVCG/OpenCV-installation-error.html">手动安装的 OpenCV2.2.0</a> 无法正确读取视频内容，用函数 cvCaptureFromAVI() 及 cvGetCaptureProperty() 均提示说失败：
<p>所有的测试视频在 Windows 下用 OpenCV2.2.0 是可以正常读取的，应该是 ffmpeg 安装不完全或是不正确。</p>
</li>
<li>从源里安装 OpenCV2.1 后，可以打开视频读取数据，可是在读取视频帧内容的时候，却提示如下错误：
<pre>
[swscaler @ 0x94b3e80]No accelerated colorspace conversion found from yuv420p to bgr24.
</pre>
<p>这个问题应该是 OpenCV 在用 ffmpeg 解压 yuv420 数据时出错。</p>
</li>
</ol>
<p>对于上述问题，可以采用下面的办法来解决：</p>
<ol>
<li>重新安装 ffmpeg x264：<a href="http://ubuntuforums.org/showthread.php?t=786095">Install and use the latest FFmpeg and x264</a></li>
<li>再重新<a href="http://opencv.willowgarage.com/wiki/InstallGuide_Linux">安装 OpenCV</a>，经测试，可以正确安装 OpenCV 2.3.1 版本，安装成功后，视频读写一切正常。</li>
</ol>
<p>另外：如果是在 Ubuntu-Server 版下安装 OpenCV，在安装 libhighgui-dev 的时候，需要安装很多和桌面相关的依赖包。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/ubuntu-opencv-read-video-problem.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jetty 内嵌网页服务器新手指南</title>
		<link>http://blog.waterlin.org/articles/java-jetty-embedded-web-server.html</link>
		<comments>http://blog.waterlin.org/articles/java-jetty-embedded-web-server.html#comments</comments>
		<pubDate>Sun, 06 Nov 2011 13:33:53 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/java-jetty-embedded-web-server.html</guid>
		<description><![CDATA[想弄一个 Java 内嵌网页服务器 ( Embedded Web Server )，这样，在我的 Java 应用程序里，可以直接提供网页服务，而不用再给用户配置一个网页服务器。对于轻量级的本地网页服务，这样就足够了！ 在 Java 应用里内嵌一个网页服务器，Jetty 是一个很好的选择。以下是我在摸索过程中，总结的基本步骤： 1. Jetty 环境的配置 首先从官方网站下载开发包，再解压到你喜欢的目录，Java 的东西就是方便呀！ 注意，Jetty 还分好几种包，Jetty@eclipse、Jetty@codehaus 是比较常见的，内容应该差不多，应该只是镜像罢了。 2. 在 Eclipse 里建立 Jetty 内嵌网页服务器 Hello World 程序 Java 开发中使用第三方库的时候，就需要把该库添加到工程里。Jetty 的库文件，全部在解压目录的 lib 目录下，比如说，在我这里就是 D:\eclipse\jetty-hightide-8.0.4.v20111024\lib 目录。在 Eclipse 里新建一个 Java 工程，同时，在工程上点右键，弹出的菜单里，选择&#8221;Properties&#8221;，打开工程属性对话框，进行如下操作： 在 &#8220;Java Build Path&#8221; ==&#62; &#8220;Libraries&#8221; 选项卡里，选择 &#8220;Add External JARs&#8221; 按钮，然后切换到 Jetty 目录里的 [...]]]></description>
			<content:encoded><![CDATA[<p>想弄一个 Java 内嵌网页服务器 ( Embedded Web Server )，这样，在我的 Java 应用程序里，可以直接提供网页服务，而不用再给用户配置一个网页服务器。对于轻量级的本地网页服务，这样就足够了！</p>
<p>在 Java 应用里内嵌一个网页服务器，<a href="http://jetty.codehaus.org/jetty/">Jetty</a> 是一个很好的选择。以下是我在摸索过程中，总结的基本步骤：</p>
<div class="outline-3">
<h3 id="sec-1.1">1. Jetty 环境的配置</h3>
<div class="outline-text-3">
<p>首先从官方网站<a href="http://docs.codehaus.org/display/JETTY/Installing+Jetty-6.1.x">下载开发包</a>，再解压到你喜欢的目录，Java 的东西就是方便呀！</p>
<p>注意，<a href="http://wiki.eclipse.org/Jetty/Starting/Downloads">Jetty 还分好几种包</a>，Jetty@eclipse、Jetty@codehaus 是比较常见的，内容应该差不多，应该只是镜像罢了。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.2">2. 在 Eclipse 里建立 Jetty 内嵌网页服务器 Hello World 程序</h3>
<div class="outline-text-3">
<p>Java 开发中使用第三方库的时候，就需要把该库添加到工程里。Jetty 的库文件，全部在解压目录的 lib 目录下，比如说，在我这里就是</p>
<pre>
D:\eclipse\jetty-hightide-8.0.4.v20111024\lib
</pre>
<p>目录。在 Eclipse 里新建一个 Java 工程，同时，在工程上点右键，弹出的菜单里，选择&#8221;Properties&#8221;，打开工程属性对话框，进行如下操作：</p>
<p>在 &#8220;Java Build Path&#8221; ==&gt; &#8220;Libraries&#8221; 选项卡里，选择 &#8220;Add External JARs&#8221; 按钮，然后切换到 Jetty 目录里的 lib 目录，把所有的 jar 包都添加到工程里。</p>
<p>现在，我们可以用<a href="http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty#Creating_a_Server">最简单的例子</a>来启动一个 Jetty 内嵌网页服务器，但是这个代码，只可以获得一个 404 错误。不过没有关系，这起码可以证明 Jetty Server is Ready！</p>
<p>相比于上面这个 404 错误的例子，相信你会更喜欢下面这个 <a href="http://wiki.eclipse.org/Jetty/Tutorial/Jetty_HelloWorld#Writing_a_HelloWorld_Example">HelloWorld 例子</a>：</p>
<pre>
<span>import</span> <span>javax</span>.<span>servlet</span>.<span>http</span>.<span>HttpServletRequest</span>;
<span>import</span> <span>javax</span>.<span>servlet</span>.<span>http</span>.<span>HttpServletResponse</span>;
<span>import</span> <span>javax</span>.<span>servlet</span>.<span>ServletException</span>;

<span>import</span> <span>java</span>.<span>io</span>.<span>IOException</span>;

<span>import</span> <span>org</span>.<span>eclipse</span>.<span>jetty</span>.<span>server</span>.<span>Server</span>;
<span>import</span> <span>org</span>.<span>eclipse</span>.<span>jetty</span>.<span>server</span>.<span>Request</span>;
<span>import</span> <span>org</span>.<span>eclipse</span>.<span>jetty</span>.<span>server</span>.<span>handler</span>.<span>AbstractHandler</span>;

<span>public</span> <span>class</span> <span>HelloWorld</span> <span>extends</span> <span>AbstractHandler</span>
{
    <span>public</span> <span>void</span> <span>handle</span>(<span>String</span> <span>target</span>,
                       <span>Request</span> <span>baseRequest</span>,
                       <span>HttpServletRequest</span> <span>request</span>,
                       <span>HttpServletResponse</span> <span>response</span>)
        <span>throws</span> <span>IOException</span>, <span>ServletException</span>
    {
        response.setContentType(<span>"text/html;charset=utf-8"</span>);
        response.setStatus(<span>HttpServletResponse</span>.SC_OK);
        baseRequest.setHandled(<span>true</span>);
        response.getWriter().println(<span>"&lt;h1&gt;Hello World&lt;/h1&gt;"</span>);
    }

    <span>public</span> <span>static</span> <span>void</span> <span>main</span>(<span>String</span>[] <span>args</span>) <span>throws</span> <span>Exception</span>
    {
        <span>Server</span> <span>server</span> = <span>new</span> <span>Server</span>(8080);
        server.setHandler(<span>new</span> <span>HelloWorld</span>());

        server.start();
        server.join();
    }
}
</pre>
</div></div>
<div class="outline-3">
<h3 id="sec-1.3">3. 其它添加 Jetty 库文件的方法</h3>
<div class="outline-text-3">
<p>如果需要在 Java 工程里进行 Embeded Server 开发，也可以把 Jetty 的库目录包含到 <a href="http://cn.waterlin.org/Java/Java.html#Java-Path-Variables">CLASSPATH 环境变量</a>里。事实上，只要能找到<a href="http://docs.codehaus.org/display/JETTY/Embedding+Jetty">下面几个文件</a>就可以了：</p>
<pre>
servlet-api-3.0.jar
jetty-util-8.0.4.v20111024.jar
jetty-8.x.jar
</pre>
<p>手册上是这样写的，不过最后一个 jetty-8.x.jar 文件，我没有找到。</p>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/java-jetty-embedded-web-server.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio 2008 环境变量的配置</title>
		<link>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html</link>
		<comments>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html#comments</comments>
		<pubDate>Mon, 31 Oct 2011 07:43:48 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html</guid>
		<description><![CDATA[在调试 Visual Studio 2008 程序时，经常有一些动态链接库（即 dll 文件）需要加载到工程里，这样才能依赖第三方库进行程序调试。 这些动态链接库，往往都是测试版本或是开发中的版本，或者会有若干个版本；这个时候，如果直接把 dll 所在目录加到 PATH 里，则会有潜在冲突的危险；如果直接拷贝到 Visual Studio 的目录下，假如测试工程太多，每次有新版本的动态链接库更新时，你需要更新若干次，拷贝、粘贴苦不堪言。 在开发过程中，究竟怎样来让 Visual Studio 链接这些 lib 及 dll 文件会比较好呢？ 总体上来说，有几种方法可以改变 Visual Studio 的环境变量设置： 直接添加到系统的 PATH 变量里： 这个方法最简单，也最直接，但是坏处是会影响全局的 PATH 设置，尤其是你包含着大量测试用的 dll 时。 在 Visual Studio 全局设置里，把 dll 所在目录添加到 PATH 里： 通过 Visual Studio 菜单 ==&#62; 工具 ==&#62; 选项 ==&#62; 项目和解决方案 ==&#62; VC++目录，在下拉框里选择&#8221;可执行文件&#8221;，然后把 [...]]]></description>
			<content:encoded><![CDATA[<p>在调试 Visual Studio 2008 程序时，经常有一些动态链接库（即 dll 文件）需要加载到工程里，这样才能依赖第三方库进行程序调试。</p>
<p>这些动态链接库，往往都是测试版本或是开发中的版本，或者会有若干个版本；这个时候，如果直接把 dll 所在目录加到 PATH 里，则会有潜在冲突的危险；如果直接拷贝到 Visual Studio 的目录下，假如测试工程太多，每次有新版本的动态链接库更新时，你需要更新若干次，拷贝、粘贴苦不堪言。</p>
<p><strong>在开发过程中，究竟怎样来让 Visual Studio 链接这些 lib 及 dll 文件会比较好呢？</strong></p>
<p>总体上来说，有几种方法可以改变 Visual Studio 的环境变量设置：</p>
<ol>
<li>直接添加到<a href="http://blog.waterlin.org/articles/setting-emacs-home-directory.html">系统的 PATH 变量里</a>：
<p>这个方法最简单，也最直接，但是坏处是会影响全局的 PATH 设置，尤其是你包含着大量测试用的 dll 时。</p>
</li>
<li>在 Visual Studio 全局设置里，把 dll 所在目录添加到 PATH 里：
<p>通过 Visual Studio 菜单 ==&gt; 工具 ==&gt; 选项 ==&gt; 项目和解决方案 ==&gt; VC++目录，在下拉框里选择&#8221;可执行文件&#8221;，然后把 dll 所在路径添加进去。</p>
</li>
<li>直接把所有 dll 拷贝到 Visual Studio 工程目录下，或是拷贝到生成可执行文件的文件夹（默认情况下是 Debug 或 Release 目录）下：
<p>这个方法也很简单，但是当你有若干个工程时，你每次更新 SDK 及其 dll 文件，你就要把所有的工程都更新，这个不符合文件唯一性的工程性准则。</p>
</li>
<li>在调试程序时，让 Visual Studio 帮你切换当前工作目录到 dll 相应的目录下：
<p>在 Visual Studio ==&gt; Project ==&gt; Properties ==&gt; Select Configuration ==&gt; Configuration Properties ==&gt; Debugging ==&gt; Working directory 里填上 dll 所在目录，这样当在调试程序时，Visual Studio 会把当前工作目录切换到这个目录下，从而会自动读取本目录下的 dll 文件。</p>
<p>这个方法的优点很明显，简单！副作用也很明显，在你切换了当前工作目录后，你可能会找不到程序的配置文件，在程序里写的诸如&#8221;./config.ini&#8221;全部都找不到了；另外，你要把所有的 dll 都放到这个工作目录里，否则一样会提示说找不到 xxx.dll 的问题。</p>
</li>
<li>最后一个方法，也是我认为最好的一个方法，在 Visual Studio 工程属性里把一个目录临时添加到 PATH 环境变量里：
<p>MSDN 上也有类似的介绍：<a href="http://msdn.microsoft.com/en-us/library/ms173406.aspx">How to: Set Environment Variables for Projects</a>，方法很简单，在 &#8220;工程属性&#8221; ==&gt; &#8220;调试&#8221; ==&gt; &#8220;环境&#8221;里，添加类似如下所示的内容：</p>
<pre>
PATH=%PATH%;$(TargetDir)\DLLS
</pre>
<p>这样就可以把 $(TargetDir)\DLLS 临时添加到该工程所属的系统 PATH 里。</p>
</li>
</ol>
<p>大家可以根据项目的实际情况，灵活选用以上方法。</p>
<p>注：本文撰写时参考了 StackOverflow 上的讨论话题：<a href="http://stackoverflow.com/questions/428085/how-do-i-set-a-path-in-visual-studio">How do I set a path in visual studio?</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/how-to-set-visual-studio-dll-path.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Org Mode 标记语言的一些疑问</title>
		<link>http://blog.waterlin.org/articles/emacs-org-mode-subscripter-setting.html</link>
		<comments>http://blog.waterlin.org/articles/emacs-org-mode-subscripter-setting.html#comments</comments>
		<pubDate>Sun, 09 Oct 2011 09:46:28 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[Emacs]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/emacs-org-mode-subscripter-setting.html</guid>
		<description><![CDATA[在 Emacs Org Mode 里，默认情况下 _ 这种字符会被当成标记语言来进行转义。有的时候，如果你只是写写文章，这种默认的转义，会让你很不方便，尤其是你在写一篇介绍技术的文章，里面出现的变量名有很多的下划线。这时，你会说：&#8221;Oh, my god! 难道要我一个一个去标记不让 _ 转义么？&#8221; 如何设置让 Org Mode 在默认情况下，不转义 _ 字符呢？ 单个 org 文件的解决办法 你可以在一个 org 文件的开头，用下面的设置来关闭这个功能。 #+OPTIONS: ^:nil 如果你需要更方便的设置，可以把上面这个改为 #+OPTIONS: ^:{} 这样，当你写 a_{b} 时，_ 后被 {} 括起来的内容就会被转义，而写 a_b 时，就按普通的方式来显示。 org sites 的解决办法 如果你是用 org sites 来写笔记，想让某个 site 的所有 org 文件不转义 _ 字符，则也可以直接在 org sites 配置文件里，配置下面这么一句，一了百了： (setq org-export-with-sub-superscripts [...]]]></description>
			<content:encoded><![CDATA[<p>在 <a href="http://blog.waterlin.org/articles/how-to-set-emacs-org-and-muse-faces.html">Emacs Org Mode</a> 里，<a href="http://orgmode.org/manual/Subscripts-and-superscripts.html">默认情况下 _ 这种字符会被当成标记语言来进行转义</a>。有的时候，如果你只是写写文章，这种默认的转义，会让你很不方便，尤其是你在写一篇介绍技术的文章，里面出现的变量名有很多的下划线。这时，你会说：&#8221;Oh, my god! 难道要我一个一个去标记不让 _ 转义么？&#8221;</p>
<p><strong>如何设置让 Org Mode 在默认情况下，不转义 _ 字符呢？</strong></p>
<div class="outline-3">
<h3 id="sec-1.1">单个 org 文件的解决办法</h3>
<div class="outline-text-3">
<p>你可以在一个 org 文件的开头，用<a href="http://orgmode.org/manual/Export-options.html">下面的设置</a>来关闭这个功能。</p>
<pre>
#+OPTIONS: ^:nil
</pre>
<p>如果你需要更方便的设置，可以把上面这个改为</p>
<pre>
#+OPTIONS: ^:{}
</pre>
<p>这样，当你写</p>
<pre>
a_{b}
</pre>
<p>时，_ 后被 {} 括起来的内容就会被转义，而写 <strong>a_b</strong> 时，就按普通的方式来显示。</p>
</p></div>
</p></div>
<div class="outline-3">
<h3 id="sec-1.2">org sites 的解决办法</h3>
<div class="outline-text-3">
<p>如果你是<a href="http://blog.waterlin.org/articles/publish-org-files-to-html-project.html">用 org sites 来写笔记</a>，想让某个 site 的所有 org 文件不转义 _ 字符，则也可以直接在 org sites 配置文件里，配置下面这么一句，一了百了：</p>
<pre>
(setq org-export-with-sub-superscripts nil)
</pre>
<p>也可以<a href="http://orgmode.org/manual/Publishing-options.html">在 org sites 里设置这个属性</a>，只作用于某一个 site：</p>
<pre>
:sub-superscript nil
</pre>
<p>如果需要像上面一样，采用相对智能的 {} 方式，可以设置成</p>
<pre>
:sub-superscript {}
</pre>
<p>或是直接用 elisp 来设置全局的属性：</p>
<pre>
(setq org-export-with-sub-superscripts '{})
</pre>
<p>这样就会<a href="http://stackoverflow.com/questions/698562/disabling-underscore-to-subscript-in-emacs-org-mode-export">用 {} 来转义</a>了。</p>
</p></div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/emacs-org-mode-subscripter-setting.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>写了两篇技术小结的笔记</title>
		<link>http://blog.waterlin.org/articles/two-blog-posts-about-db-and-opencv.html</link>
		<comments>http://blog.waterlin.org/articles/two-blog-posts-about-db-and-opencv.html#comments</comments>
		<pubDate>Fri, 09 Sep 2011 13:18:34 +0000</pubDate>
		<dc:creator>waterlin</dc:creator>
				<category><![CDATA[技术]]></category>

		<guid isPermaLink="false">http://blog.waterlin.org/articles/two-blog-posts-about-db-and-opencv.html</guid>
		<description><![CDATA[最近折腾得够呛，天天写代码，都没时间更新博客了。 总结一下最近碰到的两个问题，写到中文 Wiki 里了，希望对大家有点帮助。 OpenCV 在 Ubuntu 11.04 平台上的编译 最近要迁移大把工作成果到 Linux 平台，即要在 Linux 下大量地折腾与 OpenCV 相关的代码。很久没有在 Linux 上折腾了，时过境迁，同样碰到了不少问题，写成日志《OpenCV 各种安装错误汇总》。 Berkeley DB 数据库的操作还是蛮有技巧的，如果需要把内存里结构比较复杂的数据写到 Berkeley DB 里，我当然拥有我的技巧，以把 IplImage 数据写入到 Berkeley DB 为例，介绍我对这一技术的理解。]]></description>
			<content:encoded><![CDATA[<p>最近折腾得够呛，天天写代码，都没时间更新博客了。</p>
<p>总结一下最近碰到的两个问题，写到<a href="http://cn.waterlin.org">中文 Wiki</a> 里了，希望对大家有点帮助。</p>
<ol>
<li>OpenCV 在 Ubuntu 11.04 平台上的编译
<p>最近要迁移大把工作成果到 Linux 平台，即要在 Linux 下大量地折腾与 OpenCV 相关的代码。很久没有在 Linux 上折腾了，时过境迁，同样碰到了不少问题，写成日志<a href="http://cn.waterlin.org/CVCG/OpenCV-installation-error.html">《OpenCV 各种安装错误汇总》</a>。</p>
</li>
<li>Berkeley DB 数据库的操作还是蛮有技巧的，如果需要把内存里结构比较复杂的数据写到 Berkeley DB 里，我当然拥有我的技巧，以<a href="http://cn.waterlin.org/Database/BerkeleyDB-data-mapping.html">把 IplImage 数据写入到 Berkeley DB</a> 为例，介绍我对这一技术的理解。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.waterlin.org/articles/two-blog-posts-about-db-and-opencv.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

