2008年12月4日星期四

2. libapr skeleton code

I believe it is a good idea to write 'skeleton code' at first, when you start to learn a new library or a new framework programming. 'skeleton code' is the smallest source code, but you can compile and execute it (although it usually do nothing useful).

当我们学新的LIB或者框架时,龙骨代码是个不错的点子,这玩意包含了代码的最小单元,但是却不做任何事情。

Fortunately, libapr's skeleton code is much simpler than other modern frameworks. Let's take a look at apr-skeleton.c. We call apr_initialize() at the initialization, and call apr_terminate() at the finalization. That's all. As you can imagine, the code does nothing.

运气不错,APR的龙骨代码比起其他框架非常精炼,打开apr-skeleton.c,

int main(int argc, const char *argv[])
{
apr_status_t rv;

/* per-process initialization */
rv = apr_initialize();
if (rv != APR_SUCCESS) {
assert(0);
return -1;
}

/* application impl. */

apr_terminate();
return 0;
}


调用apr_initialize()进行初始化,调用apr_terminate()完成,就这些,也正如你所想,这段代码什么也没做。

Here, we have some libapr programming styles and rules:

* naming rule is very simple and clear.
* opaque data types are commonly used (a.k.a. incomplete types)
* most of return types are apr_status_t. As a result, result-arguments are commonly used.
* memory pool rules

我们给出一些libapr编程的风格和规则:
* 命名规则非常简单和清楚。
* 不透明类型被广泛地使用。(又名不完整类型)
* 返回结果或是结果输出参数大多数返回类型为apr_status_t。
* 内存池规则。

We are able to see these styles in the following code.

/* excerpted from mp-sample.c */

apr_status_t rv;
apr_pool_t *mp;
rv = apr_pool_create(&mp, NULL);

I will describe the meaning of the code. Here, please take a look at only style. You can see apr_ prefix. The apr_ prefix indicates that the symbol is in libapr naming scope. You can see _t suffix. It indicates that the symbol is a type name.

我们经常能看见以下这种代码:
/* excerpted from mp-sample.c */

apr_status_t rv;
apr_pool_t *mp;
rv = apr_pool_create(&mp, NULL);
apr_为前缀表示是LIBAPR的代码,_t表示是一种抽象类型,多数都是结构体。

apr_pool_t is opaque type. It means the type's structure is not public. By OO(Object Oriented) terminology, all member variables are private. You can't touch them directly. Furthermore, you can't see them in public header files. All you can do for the type is to call APIs such as apr_foo_bar() functions. Most importantly, you can't allocate their instance memories directly. All you can do is to call construct APIs. Only libapr knows how to construct and destruct the objects.
apr_pool_t是一个分装的类,这意味着类型的结构体不是公开的,根据OO(面向对象)的思维,所有成员变量都是私有的。我们不能直接操作他们,此外,我们也没必要去关心公共头文件。例如我们会用到名字像apr_foo_bar()这样的函数,要注意的是,我们并不需要关心怎么去给他们分配内存,当我们需要调用这些API的时候,libapr知道怎么去构造和销毁他们。

As you see, apr_pool_create()'s return type is apr_status_t. apr_status_t is either status code or error code. apr_status_t is a commonly used as return types of most APIs. Accordingly, we can get results from functions by arguments. Such arguments are called result-argument. There are many result-arguments in the libapr world.
正如你所见,apr_pool_create()返回类型是 apr_status_t, apr_status_t是一种状态码和错误码。 apr_status_t是最常用的返回类型。相应的,我们能通过各种参数调用函数来得到各种类型的结果。当然,libapr也使用了相当多的返回参数。

In general, if you see apr_foo_t type, you will see apr_foo_bar() functions, which are related to apr_foo_t type. The following code is a typical pseudo code.

/* pseudo code of libapr. error checks omitted */
apr_status_t rv;
apr_foo_t *foo;
rv = apr_foo_create(&foo, args...);/* create a @foo object by @args */
rv = apr_foo_do_something(foo, args...); /* do something with @foo */
apr_foo_destroy(foo);

一般情况下,如果看见apr_foo_t类型,一般会有apr_foo_bar()方法,他使用到apr_foo_t类型,如这种很典型的代码。

没有评论: