Enterprise Just Builder

Solution for Enterprise Software Architecture

框架与类库

将 Win32 枚举型 APIs 转换为 STL 迭代器

原文1

操作系统都有许多 API 用于存取实体集合的,比方说 Unix 的 opendir()/readdir() 函数。Win32 API 也提供了许多函数用来枚举集合内的元素,通常采用的模型无外乎下面几种:回调函数 (如 EnumChildWindows), get-first/get-next (取第一个/取下一个 比如FindFirst/NextFile), 或 get-nth (取第n个 如 RegEnumValue) — 其语义和前二者完全不同。

现在 C++ 社区正在逐步朝着符合 STL 的通用编码格式迈进,如使用容器 (序列和关联)、迭代器、泛函 (或函子或函数对象)、算法和适配器等等。这一做法的最大好处是可以采用一种通用的方法操纵不同的实体, 大大减少开发者的工作量, 同时提高健壮性、可维护性和重用。

STL 技术未被广泛运用的原因之一是除了标准库所提供的类和函数 (list, vector, for_each 等) 之外, 缺少可用的 STL 兼容库, 特别对于操作系统 API。原因之一是这涉及编程模型之间迁移转换的复杂性, 特别是对于集合和序列。本文通过将两种 Win32 枚举模型实际转换 STL 序列, 创建封装了 Win32 API 的轻量级序列类, 并提供了可按 STL 标准算法来操纵枚举实体的迭代器。

本文所演示的类是 WinSTL 库的一部分,WinSTL 则是 STLSoft 的子项目。STLSoft 是个开源组织,一直致力于将 STL 概念运用到多种技术和操作系统中去。

>>> 阅读全文

 

, , , ,

Hazelcast 简介

Hazelcast 是一个开源的内存数据网格(IMDG)解决方案,它提供了可伸缩的分布式内存计算,对提高应用性能来说,Hazelcast 公认是最快且最具可扩展性的途径。特别是, 它提供大家十分熟悉的 Java 接口如 Map, Queue, ExecutorService, Lock, JCache 等的分布式实现,使得分布式计算变得更为简单。比如通过 Map 接口提供了内存键值存储,在保持了友好性的同时,还获得 NoSQL 的诸多优势的同时,提高了生产力。

除了分布式内存数据结构,Hazelcast 还提供一整套方便的 API 来访问集群中的 CPU 从而得到最快的处理速度。Hazelcast 设计目标之一是轻量化、便于使用。 因此 Hazelcast 的分发包只有一个紧凑的库 (JAR)文件,除了 Java 它不依赖其他东西,因此很容易将它插入解决方案中,从而得到分布式数据结构和分布式计算的能力。

Hazelcast is highly scalable and available. Distributed applications can use Hazelcast for distributed caching, synchronization, clustering, processing, pub/sub messaging, etc. Hazelcast is implemented in Java and has clients for Java, C/C++, .NET as well as REST. Hazelcast can also speak memcache protocol. It also plugs in to Hibernate and can easily be used with any existing database system.

If you are looking for In-Memory speed, elastic scalability and the developer friendliness of NoSQL, Hazelcast is a great choice for you.

 

, , ,

Microsoft Bond C++ 使用手册

文章评价:

Bond 是微软开发的数据结构化(schema)处理框架,它支持跨语言的序列化与反序列化,支持强大的泛型机制,因此能够对数据进行有效地处理。该框架在微软公司内部的高扩展服务中得到了广泛的应用。Bond 可适用于服务间通信、大数据存储和处理等诸多应用场景。

Bond 定义了一个富类型系统和一套 schema 版本控制规则以提供前后向的兼容性。Bond 的核心功能包括高性能的数据序列化/反序列化和一个强大的通用数据转化机制。通过可插拔的序列化协议、数据流和用户自定义类型别名(user defined type aliases)等机制,由此 Bond 实现了高可扩展性。

目前该项目已经基于宽松的 MIT 许可开源在了 GitHub 上,当前版本支持 C++、C# 和 Python,可运行 在Linux、OS-X 和 Windows 平台上。Bond 的编译器完全是使用 Haskell 编写的。

Bond 与其他序列化系统具有很多相似性,例如 Google Protocol Buffers (ProtoBuf)、Thrift 以及 Avro等等。和它们相比,Bond 有以下特点:

>>> 阅读全文

 

, , ,

C++ 模板编程入门 (一)

于天生的畏惧,大多数 c++ 程序员都尽量远离模板技术,反对的声音有:

  • 模板难以学习和运用
  • 编译时的错误信息模糊又冗长
  • 不值得花费精力

我承认模板都有点难以学习、理解和运用。但是从模板中获得的益处会多于其负面影响。许多泛型函数或类都可以被模板所包装。我后面会加以解释。

虽然从技术上来看 c++ 模板与 STL (标准模板库) 是同门兄弟。不过在本文中,我将只涵盖模板的核心部分。在下一篇文章中,我会阐述更高级且有趣的模板技术以及使用 STL 的一些诀窍。

语法
你可能已经知道,大部分模板都使用尖括号:小于号(<)和大于号(>),其使用形式总是如下所示:

< Content >

这里的 Content 可以是:

>>> 阅读全文

 

, ,

.NET 编译平台 (Roslyn) 概述

文章评价:
一直以来,编译器都按黑盒的方式运作 — 这头放入源代码,中间部分施展魔法,在另一头就会生成目标文件或程序集。当编译器施展魔法时,它建立了对代码的深刻理解,但这些知识除了实现编译器的巫师外,旁人无法掌握。一旦生成编译输出,这些信息就被彻底忘却。几十年来,这种方式一直运作良好,但现在却不能满足需要了。

如今为了提高生产力, 人们越来越依赖于集成开发环境(IDE)所提供的智能感知、重构、智能重命名、 “查找所有引用” 和 “转到定义” 等功能。我们用代码分析工具来改善代码质量,用代码生成器来协助代码构建。想要让这些工具更聪明,就需要它们能更多地访问编译器,同时也需要对编译器中深厚的代码处理知识有更多的了解。

这就是 .NET 编译器平台(“Roslyn”)的核心使命:打开黑盒让工具和用户可以分享编译器处理代码时的大量信息。与 “源代码—目标文件”的直译方式不同,Roslyn 使编译器成为平台,这意味着工具和应用程序可以通过 API 来处理代码相关的任务。

将编译器过渡到平台,这大大降低了构建代码相关(code focused)工具与程序的门槛,在许多方面推动了创新,包括:元编程、代码生成、代码转化、C#\VB 的交互式使用、领域特定语言内嵌 C#\VB 等等。

在 .NET 编译器平台 (“Roslyn”) SDK 预览版中包括了最新的语言对象模型,可用于代码生成、代码分析与重构。我们还包括了一些 API 草稿,以便在后续的版本中实现支持脚本、C#\VB的交互式使用。本文是对 .NET 编译器平台(“Roslyn”)的概念性描述,更多情况可以参考预览版 SDK 中的演示与示例。

>>> 阅读全文

 

, , , , , , , ,

用 libclang 实现代码生成器

文章评价:
代码生成器对大型 C++ 项目而言是非常有用的工具。由于语言层面上缺乏自省(introspection)机制,要实现反射、脚本绑定(script binding)及序列化都需要编写代码样板(boilerplate) 以保留相关信息,否则在编译时这些数据会全部被丢弃。大部分解决方案要嘛是侵入式的(严重依赖于宏 — Macro,结果难以调试且要求怪异的语法声明)要嘛非常脆弱(fragile)(要根据实际代码不断更新样板,常常没有任何警告就中止运行)。提高鲁棒性的方法之一是自动生成这类样板。要实现这一目标,需要用某种方式解析代码,换句话说,需要了解什么信息该被保留。然而,解析 C++ 本身就是极其复杂的工作,要考虑各种怪异情况,如果真想这样做,消费的时间可能相当漫长。 1

即使只针对 C++ 某个“差堪可用”的子集进行解析,这类尝试要嘛失败了要嘛对编码规则有严格要求。也就是说,要求避免使用解析器无法理解的语法 — 一旦有人不按规矩提交代码解析器就会中止工作。要解决这个问题,我发现 LLVM 项目中有一个很好的工具:libclang2。由于 CLANG C++ 前端 和 libclang 调用的代码是相同的,所以它了解 C++ 的一切。该类库的最新发布可以支持 C++1x(如不出意外将是 C++14)的功能。唯一略有欠缺的是文档方面:其官方文档不过是 Doxygen 生成的参考,虽然有用,但不足以介绍如何使用该类库;加上问题本身的复杂性,学习曲线将十分陡峭。

本文要讲述的是如何用 libclang 及其 Python 绑定来实现一个实用的 C++ 代码生成器。在某种意义上,“实用” 意味着这不是一个通用的解决方案。这里所演示的不是某种具体的实现,而是一种解决问题的思路、一个详细的范例。借助这些想法,你可以自己创建通用的反射方案。本文的另一设计原则是尽力减少代码侵入以便能按自然 C++ 语法编写代码。同时我也鼓励读者自己动手,从头开始尝试实现自己的代码生成器。

我必须感谢 Eli Bendersky 的有关帖子3,它是我收集的资料中最好的参考之一。

准备工作
要读懂本文,读者可能需要具备以下知识点:

>>> 阅读全文

 

, , , , ,

用 RapidMiner 进行情感分析 (一)

RapidMiner(社区版,AGPL)是一个免费的开源分析工具,由于其灵活性和鲁棒性,它也成为了一个优秀的原型平台。RapidMiner 提供了一整套完整的算法,允许你快速切换来尝试不同的模型。 使用 RapidMiner 无需编码,但也提供了 R 语言和 Groovy 插件。RapidMiner 基于 Java 的,所以可以在任何平台上运行。这里我会演示如何用监督学习(Supervised learning)来创建一个人气模型以展示其灵活性。

本文将对 RapidMiner 做一个基本介绍,所以我会详细介绍每一个步骤如何进行。

在机器学习(Machine learning)领域,监督学习(Supervised learning)、非监督学习(Unsupervised learning)以及半监督学习(Semi-supervised learning)是三类研究比较多,应用比较广的学习技术,wiki 上对这三种学习的简单描述如下:

  • 监督学习:通过已有的一部分输入数据与输出数据之间的对应关系,生成一个函数,将输入映射到合适的输出,例如分类。
  • 非监督学习:直接对输入数据集进行建模,例如聚类。
  • 半监督学习:综合利用有类标的数据和没有类标的数据,来生成合适的分类函数。

由于本文将使用监督学习,首先我们需要一组标签数据。这里我们将使用康奈尔大学 Pang 和 Lee 所提供movie review data,大小为 2K. 同时你还可以在该站点上找到不少在情感分析方面很有价值的论文。

本文处理记录所用的 RapidMiner 版本为 5.2.017,并带有文字处理扩展插件。 Java 版本为 1.6。本系列分为两部分,在第一部分中重点将放在展示如何构建一个人气模型。您可以点击屏幕截图来查看大图。

>>> 阅读全文

 

, , ,

GPerf 和完美哈希函数

GNU Gperf 工具用来生成一种 “完美的” 散列函数(perfect hash function),可以将用户提供的一组特定字符串生成散列表、散列函数和查找函数的 C/C++ 代码。 所谓完美散列函数或完美 Hash 函数,指存在这样一个 hash 函数 F,可以将一个含有 n 元素的用户特定关键字集合 N 到集合 W, N 的关键字被唯一映射到 W 的 0..k-1 范围,其中 k>=n。如果 k=n 那么 F 就是“最小化完美 hash 函数”。

最小化完美 hash 函数具有两个特性:

  • 只需要执行一次查找就能完成静态搜索结构中的关键字识别,即所谓的“完美”。
  • 为保存关键字所分配的内存刚刚可以容纳关键字集合,不会多余。即“最小化”。

Gperf 被普遍地用在多种商业编译器、研究型编译器、语言处理工具的词法分析器上,用来生成关键字识别器,包括:GNU C, GNU C++, GNU Pascal, GNU Modula 3 和 GNU indent 等等。Gperf 将从用户提供的文件中(即关键字文件,通常使用 .gperf 作为扩展名,但不做强制要求)生成 C/C++ 源代码。所有代码被定向到标准输出,然后必须重定向到类似下面的文件:

gperf  -L C++ keyfile.gperf > perfecthash.hpp

注意: -L 选项将指示 gperf 生成 C++ 代码。

Gperf 会生成一个 0..K 元素的静态查找结构和一对 C 函数的源代码。利用这些函数只需要一次查找,就可以判断给定的字符串 S 是否在集合 W 中。这两个函数是:

>>> 阅读全文

 

, , ,

如何创建灵活的可重用的 WCF 服务

简介
你也许知道,要创建可靠的多层应用程序来说,设计和创建一个灵活且可重用的服务层是必不可少的。在这篇文章中,我们要讨不同的构建服务层的方法及其利弊。您将学习一些可以帮助构建可重用服务的设计模式,我们还会演示如何用开源的 Xomega 框架实现 WCF 服务的。

我们还将讨论在 Silverlight 中使用 WCF 的挑战,以及解决这些挑战的解决方案解决。

架构概览
在开始设计你的服务层的时候,你所面对的第一个问题是你的服务层是完全无状态的还是可能会是有状态的?

无状态服务的利与弊
对于完全无状态的服务,每个请求是完全相互独立的,所以有其优势,但不很适合建立灵活的、 可重复使用的服务,我们一会再加解释。无状态服务的好处是有很强的可扩展性和较低的资源占用率,如内存消耗和线程使用。您可以通过服务器集群对服务进行负载平衡,而且每个服务器能够独立地处理任何请求,而无需占用任何内存来存储状态,在处理完请求之后,就可以释放如线程或数据库连接等资源。

但是,不利的方面是你将不得不随每个请求传递整个状态。如果状态总是比较小,如读取/查询操作或作为一个工作单元执行的简单更新,这不可能是一个问题。在大型系统和企业应用程序,总是需要多个级别的验证,才能保存数据,但用户状态可能包含大量跨多个对象的编辑。设计一种服务,能把所有的用户编辑单个请求可以在这种情况下,是一个极具挑战性的任务,您可能需要设计一个单独的服务或操作对于每个不同的方案,这将使您的服务不重用,最终可能导致维护恶梦。

>>> 阅读全文

 

, , ,

OpenCV 使用手册 (一) 介绍OpenCV

OpenCV简介
OpenCV 是 Open Source Computer Vision Library 的缩写, 它于 1999 年由 Intel 建立,现在由 Willow Garage 提供支持。OpenCV 是一个基于 BSD 许可证授权(开源)发行的跨平台计算机视觉库,可以运行在 Linux、Windows 和 Mac OS 操作系统上,是个轻量级而且高效的类库 ,由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、Ruby、MATLAB 等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。最新版本是2.3。你可以访问官方站点以获得更多帮助。

编译
OpenCV 的官方站点提供了二进制代码的下载,但在某些场合,比如需要给源代码打补丁,这时候你可能需要从头开始编译 OpenCV 以便能得到修正的二进制代码。 现在 OpenCV 发布版本都提供了跨平台的自动化构建工具 Cmake 的方式,可以很方便地生成各种平台的 makefile。这里以 64 位 Windows 平台的的 VC++ 1.0 为例说明。

准备工作
为了编译 64 位的 OpenCV,我们需要安装的工具有 MinGW64 (GCC 4.7.2), CMake 和 Python 2.7.3(64位),这些工具主要是用来构建 Numpy 和 FFMPEG 的,后续阶段的 OpenCV 的编译依赖于这些类库。

Numpy 是 Python 下的一个基础科学的计算包,提供了矩阵、线性代数、傅立叶变换函数等等,Numpy 的编译需要用到线性代数工具包,它可以兼容于 BLAS/LAPACK,或者 ATLAS,MKS 等等实现,这里我们选用 netlib 提供的基本线性代数子程序 BLAS 和线性代数程序包 LAPACK,版本是3.3.1。编译 BLAS/LAPACK 只需要在 MSYS 中运行:

cmake -G "MSYS Makefiles"
make

编译后可以得到两个文件: libbas.a 和 liblapack.a,两个库文件拷贝到 MSYS 中的 /usr/local/lib 目录中即可。

>>> 阅读全文

 

, , , , ,

用OpenMP开发并行程序

OpenMP 是一套可于共享内存并行系统的多线程程序设计的指导语句(Compiler Directive),它最早是由 OpenMP Architecture Review Board 牵头提出的,现在OpenMP为许多厂商所支持,因此具有较高的可移植性。支持 OpenMP 的编程语言包括 C 语言、C++ 和 Fortran 等等,支持 OpenMP 的编译器包括 Sun Compiler,GNU Compiler 和 Intel Compiler,MS VC++ 等等。

OpenMP 提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的 pragma 来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。如果选择忽略这些 pragma,或者编译器不支持 OpenMP 时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。

OpenMP 提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,OpenMP 是一个很好的选择。同时,使用 OpenMP 也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。线程粒度和负载平衡等是传统多线程程序设计中的难题,但在 OpenMP 中,库函数从程序员手中接管了这两方面的部分工作。

但是,作为高层抽象,OpenMP 并不适合需要复杂的线程间同步和互斥的场合。OpenMP 的另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI 使用较多。

OpenMP 的架构
OpenMP 是作为共享内存系统的标准问世的。它是为在多处理器机上编写并行程序而设计的一个应用编程接口。它包括一套编译指导语句和一个用来支持它的函数库。

>>> 阅读全文

 

, , ,

VC++中多字节字符集和Unicode之间的互换

在Visual C++.NET中,默认的字符集是Unicode,这和Windows默认的字符集是一致的,不过在老的VC6.0等工程中,默认的字符集形式是多字节字符集(MBCS:Multi-Byte Character Set),这样导致在VC6.0中非常简单实用的各类字符操作和函数在VS2005环境下运行时会报各种各样的错误,这里总结了在Visual C++.NET2005环境中Unicode字符集下CString和char *之间相互转换的几种方法,其实也就是Unicode字符集与MBCS字符集转换。

1.Unicode下CString转换为char *
方法一: 使用API:WideCharToMultiByte进行转换

CString str = _T("你好,世界!Hello,World");
//注意:以下n和len的值大小不同,n是按字符计算的,len是按字节计算的
int n = str.GetLength();  
//获取宽字节字符的大小,大小是按字节计算的
int len = WideCharToMultiByte(CP_ACP,0,str,str.GetLength(),NULL,0,NULL,NULL);
//为多字节字符数组申请空间,数组大小为按字节计算的宽字节字节大小
char * pFileName = new char[len+1];   //以字节为单位
//宽字节编码转换成多字节编码
WideCharToMultiByte(CP_ACP,0,str,str.GetLength(),pFileName,len,NULL,NULL);
pFileName[len+1] = \0;   //多字节字符以’\0’结束

方法二:使用函数:T2A、W2A

CString str = _T("你好,世界!Hello,World");
//声明标识符
USES_CONVERSION;
//调用函数,T2A和W2A均支持ATL和MFC中的字符转换
char * pFileName = T2A(str);  
//char * pFileName = W2A(str); //也可实现转换

注意:有时候可能还需要添加引用#include
2、Unicode下char *转换为CString

方法一:使用API:MultiByteToWideChar进行转换

>>> 阅读全文

 

,

在C/C++中使用LIBXML2

文章评价:
C/C++ 标准库中并没有提供任何操作 XML 的方法,因此必须借助第三方函数库,您可以使用免费的诸如 Microsoft MSXML SDK 的商业版软件,也可以使用开源实现 expat 和 libxml2,在xmlbench上罗列了一些常见的 XML 类库及其性能比较,可以供您参考选择。这里我们主要介绍 libxml2,libxml2 是一个 C 语言的 XML 程序库,它可以包括 Windows, Linux, Mac 等等多种操作系统上使用,不但支持 DOM 和 SAX2 等等标准 XML 的解析方法,还从 C# 中借鉴了 XmlTextReader 这种简洁易懂的 pull 解析方式,此外 libxml2 支持 XPATH 查询,并且部分支持 XSLT 转换,在许多著名函数库中都有 libxml2 的身影,比如 Glib 等等。

libxml 的官方地址是XmlSoft,您可以在上面下载最新的源代码。接下来,我们先将源代码编译成平台所需的二进制文件。

编译 libxml2
在 Linux 或者 Windows 上使用 GCC 的读者可以参考用MinGW64编译Readline GetText等类库一文。这儿我们介绍一下 VC++ 的编译方法。Libxml2 依赖于 iconv 和 zlib 库。libiconv 库是一个字符编码转换工具,它提供了一个iconv()的函数,以实现一个字符编码到另一个字符编码的转换。分别下栽这些源代码,包括Zlib 1.2.5, libiconv 1.11.1 和 libxml2 2.7.8。

首先编译 libiconv,需要用 admin 权限打开 VC++ 的命令提示窗口,然后运行:

nmake -f Makefile.msvc NO_NLS=1 MFLAGS=-MT

如果需要成共享库的话,可以在参数中的添加上”DLL=1”。编译结束之后,运行 nmake -f Makefile.msvc install,默认会在 C 盘创建 usr 目录,保存得到的头文件、库文件和二进制文件。

>>> 阅读全文

 

, , , , , ,

Libffi的使用及其范例

文章评分:

LibFF I与调用约定

“FFI” 的全名是 Foreign Function Interface,通常指的是允许以一种语言编写的代码调用另一种语言的代码。而 “Libffi” 库只提供了最底层的、与架构相关的、完整的”FFI”,因此在它之上必须有一层来负责管理两种语言之间参数的格式转换。

高级语言编译器产生代码时都会依据一系列的规则,这些规则十分必要,特别是对独立编译来说。其中之一是“调用约定” (Calling Convention),它包含了编译器关于函数入口处的函数参数、函数返回值的一系列假设。它有时也被称作“ABI”(Application Binary Interface)。调用约定(Calling Conventions)定义了程序中调用函数的方式,它决定了在函数调用的时候数据(比如说参数)在堆栈中的组织方式。

通常来说函数调用要用到的两条基本的指令:”CALL”指令和”RET”指令。”CALL”指令将当前的指令指针(这个指针指向紧接在CALL指令后面的那条指令)压入堆栈,然后执行一条无条件转移指令转移到新的代码地址。”RET”是与”CALL”指令配合使用的指令,在绝大多数函数中它是最后一条指令。”RET”指令弹出返回地址(就是早些时候”CALL”指令压入堆栈的地址)并将其加载到”EIP”寄存器中,然后从这个地址开始继续执行。

>>> 阅读全文

 

, , , , ,

用MinGW64编译GTK-DOC

Linux 下有太多重复的组织文档的方式(比如 man,doxygen),对大部分用户而言,GTK-DOC 基本就是鸡肋,我们可以把它给忽略。但是如果用 GIT 下载过 Gnome 一些源代码包,很大机会你会遇到需要运行 gnome-autogen.sh 这个命令(gnome-autogen.sh在 gnome-common 这个包中)来生成 configure 文件,这时候系统就会提示 Gnome-autogen.sh 依赖于 GTK-DOC。因此你不得不编译 GTK-DOC 来解决这个依赖性问题。

GTK-DOC 的编译秉承了 Unix/Linux 的许多命令行工具的缺点– 繁琐、难用、而且基本就没啥用,只是为了折腾人。所以在这里详述 GTK-DOC 的编译过程,以解决这个让人厌恶的依赖问题。(这种依赖性在 Gnome 的包里比比皆是,比较神经质的设计)。

首先 GTK-DOC 需要用到 XMLCATALOG 这个命令,xmlcatalog 存在于 libxml2 中,所以你首先需要编译 libxml2,详细过程你可以在用MinGW64编译Readline GetText等类库一文找到。

GTK-DOC 还需要 JADE 等等依赖包,但由于我们基本不需要 GTK-DOC 的功能,这里只需要下载两个非要不可的 DTD 就可以了:就是 Docbook 4.3 DTDDocbook-XSL-DOC-1.171.1

接下来需要把这两个包安装到 xml catalog 里,这也是个庞杂混乱的过程,为此我写了两段脚本,将其拷贝到相应的源代码目录中,在 MSYS 中运行这两段脚本就简单完成: 和 。

>>> 阅读全文

 

,

Previous Posts