Posted on 27-12-2011
Filed Under (技术) by waterlin

最近都在写一些跨 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
#endif

源代码的编码格式

源代码的编码格式,最好统一用 GBK 或是 UTF-8,以避免不同编码器之间转换造成的乱码。

注意代码里的文件名大小写。

Windows 里 include 一个头文件,你的大小写可以随便写。但是在 Linux 上,你得小心了,clsssa.h 你不能写成

#include "ClassA.h"

因为在 Linux 上,文件及目录名是大小写敏感的。

一些类型名称

Windows 处理宽字符集与窄字符集采用的方法,是用宏定义来区分。比如说 TCHAR 在不同的工程下,属于不同的类型。

而在 Linux 下,则需要注意这些问题。为了让你的代码可移植性强。一定要少用 BOOL, TCHAR 这些类型,而要用原生态的 C/C++ 类型,比如说 bool, char 等。

有关 _tmain 等主函数问题。

默认情况下,Visual Studio 新建的 Win32 Console 工程,全是类似于这样的。

int _tmain(int argc, _TCHAR* argv[])
{
}

这些代码,移植到 Linux 下面,就需要我们自己做一部分工作。

如果你在 Visual Studio 用的是 Unicode 编码的,则对应的 Linux 代码应该是另外一套。我则是用宏裁剪了两个主函数出来。如果你有什么更好的方法,可以跟我分享。

注意一些库在 Linux 和 Windows 平台下的不同表现

虽然你的程序可能依赖大量的跨平台库,这些库号称是跨平台的,但是很有可能在不同的平台的表现,会有所不同。例如,log4cxx 在 Linux 和 Windows 下就会有字符集设置的差别

你在编写跨平台代码的时候,就应该特别小心这些库的细微差别,及时调整。

后记

以上是一些跨平台 C/C++ 代码编写的经验,备忘一下,也希望对大家有用。

(0) Comments    Read More   
Posted on 14-12-2011
Filed Under (技术) by waterlin

最近在 Linux 下使用 log4cxx 库,使用的 log4cxx 版本为 0.10.0,结果无法显示中文日志信息。

这可怎么办呢?我不可能把中文日志全部一行一行替换为英文的,这可是一个非常傻B的举动。

经过研究,终于知道需要经过如下步骤才能让 log4cxx 在 Linux 下正常显示中文日志:

  1. 你可以先 locale 检查一下 Linux 终端环境是不是 zh_CN ;

    $ locale
    
  2. 如果你的是 en_US 之类的编码,则需要把 locale 设置为简体中文:
    $ export LC_ALL="zh_CN.UTF-8"
    

    如果你的系统提示说没有安装本字符集,则需要用命令进行安装:

    $ sudo apt-get install language-pack-zh-hans
    
  3. 在程序里设置应用程序的 locale 和终端一样:
    LoggerPtr logger;
    log4cxx::PropertyConfigurator::configure("./log4cxx.properties");
    logger= Logger::getLogger("test") ;
    logger->info(("Start logging"));
    setlocale(LC_ALL, "zh_CN.UTF-8");   
    

    关键是最后这一句 setlocale,要设置得和终端一样,都是 zh_CN.UTF-8。

这样,你的程序就可以用 log4cxx0.10.0 输出中文日志信息了。

(2) Comments    Read More