###################################################################
# openssl MAIN PROG
# 20060313 by daineng@nj.cpsecure
# Last Modified @ 20060404
###################################################################
这个方法的主要作用是将一下独立的程序(main)在适当的时候作为一个函数
结合到一个更大的程序中去(MONOLITH)。
定义方式如下:
在{openssl}/apps/apps.h文件中
#ifndef MONOLITH
#define MAIN(a,v) main(a,v)
#ifndef NON_MAIN
CONF *config=NULL;
BIO *bio_err=NULL;
#else
extern CONF *config;
extern BIO *bio_err;
#endif
#else
#define MAIN(a,v) PROG(a,v)
extern CONF *config;
extern char *default_config_file;
extern BIO *bio_err;
#endif
再看可以产生独立小程序的源程序文件,如{openssl}/apps/ca.c。在开
始有以下定义:
#undef PROG
#define PROG ca_main
在下面有如下定义:
int MAIN(int, char **);
int MAIN(int argc, char **argv)
{
....
}
在下面有如下定义:
最后看个大程序,它是{openssl}/apps/openssl.c,这里其实没有什么
'define'或'undef'语句,但有下面这样的包含文件:
#include "progs.h"
下面我们来看这个{openssl}/apps/progs.h文件:
首先是一堆函数的声明,包含ca_main:
......
extern int ca_main(int argc,char *argv[]);
......
紧接着是一个结构:
typedef struct {
int type;
const char *name;
int (*func)(int argc, char *argv[]);
} FUNCTION;
type是函数类型,类型定义在这个结构定义之上;name是上面声明的函
数名称,对于ca_main来说就是'ca';func就是函数本身了。
下面定义了这个结构的数组,将上面声明的所有函数包含进去:
FUNCTION functions[] = {
......
{FUNC_TYPE_GENERAL, "ca", ca_main},
......
{0, NULL, NULL}
};
openssl.c就可以利用这个functions数组来以函数的方式使用所有的小
程序,这点在{openssl}/apps/openssl.h中可以看见,典型的就是遍历
这个数组,找到需要的函数类型。
编译小程序的情况:
在我们编译小程序的时候,所有的MAIN被直接替换为main。没有任何一
个地方会出现PROG名字,所以在每个小程序的源文件中关于PROG的设置
将产生不了任何作用。
编译大程序的情况:
当我们需要编译大程序的时候,定义MONOLITH,所有的MAIN(a, v)在预
编译的时候就被替换为PROG(a, v),在每个源文件中,由于对PROG的独
特的定义,PROG又会被替换成一个独特的函数名称。
如在ca.c文件中,MAIN就会被替换成这样:
int ca_main(int, char **)
在openssl.c中,就可以以ca_main子程序的方式来使用这个ca程序。
其他:
这里还出现了一个关于NON_MAIN的预编译选项。它的出现是由于在程序
中有一些都要使用到的变量,无论是在大程序还是在小程序中,像上面
的 config 和 bio_err。
在编译小程序时,由于没有定义 MONOLITH 和 NON_MAIN,在apps.h中
对 config 和 bio_err 的定义就会是这样:
CONF *config=NULL;
BIO *bio_err=NULL;
这个时候注意到 apps.h 是 apps.c 的头文件,如果不做任何处理的话
我们将得到在多个obj文件中重复定义的错误,所以在apps.c中#include
被写成这样:
#define NON_MAIN
#include "apps.h"
#undef NON_MAIN
这时对于apps.c来说,config 和 bio_err 的定义就是:
extern CONF *config;
extern BIO *bio_err;
如果是编译大程序,由于 MONOLITH 已被定义,config 和 bio_err 在
apps.h中定义都是 extern 型的,这两个变量被定义在openssl.c源文
件中:
#ifdef MONOLITH
CONF *config=NULL;
BIO *bio_err=NULL;
#endif
总结:
就像在开头说的那样,如果我们独立的编写一些小程序,在最后会合并
到一个大程序中的话,我们就可以使用这样的方式。但我觉得也有不好
的地方,int (*func)(int argc, char *argv[])这样的函数接口似乎不
是很妥当。
看情况用着吧。 ;-)
# openssl MAIN PROG
# 20060313 by daineng@nj.cpsecure
# Last Modified @ 20060404
###################################################################
这个方法的主要作用是将一下独立的程序(main)在适当的时候作为一个函数
结合到一个更大的程序中去(MONOLITH)。
定义方式如下:
在{openssl}/apps/apps.h文件中
#ifndef MONOLITH
#define MAIN(a,v) main(a,v)
#ifndef NON_MAIN
CONF *config=NULL;
BIO *bio_err=NULL;
#else
extern CONF *config;
extern BIO *bio_err;
#endif
#else
#define MAIN(a,v) PROG(a,v)
extern CONF *config;
extern char *default_config_file;
extern BIO *bio_err;
#endif
再看可以产生独立小程序的源程序文件,如{openssl}/apps/ca.c。在开
始有以下定义:
#undef PROG
#define PROG ca_main
在下面有如下定义:
int MAIN(int, char **);
int MAIN(int argc, char **argv)
{
....
}
在下面有如下定义:
最后看个大程序,它是{openssl}/apps/openssl.c,这里其实没有什么
'define'或'undef'语句,但有下面这样的包含文件:
#include "progs.h"
下面我们来看这个{openssl}/apps/progs.h文件:
首先是一堆函数的声明,包含ca_main:
......
extern int ca_main(int argc,char *argv[]);
......
紧接着是一个结构:
typedef struct {
int type;
const char *name;
int (*func)(int argc, char *argv[]);
} FUNCTION;
type是函数类型,类型定义在这个结构定义之上;name是上面声明的函
数名称,对于ca_main来说就是'ca';func就是函数本身了。
下面定义了这个结构的数组,将上面声明的所有函数包含进去:
FUNCTION functions[] = {
......
{FUNC_TYPE_GENERAL, "ca", ca_main},
......
{0, NULL, NULL}
};
openssl.c就可以利用这个functions数组来以函数的方式使用所有的小
程序,这点在{openssl}/apps/openssl.h中可以看见,典型的就是遍历
这个数组,找到需要的函数类型。
编译小程序的情况:
在我们编译小程序的时候,所有的MAIN被直接替换为main。没有任何一
个地方会出现PROG名字,所以在每个小程序的源文件中关于PROG的设置
将产生不了任何作用。
编译大程序的情况:
当我们需要编译大程序的时候,定义MONOLITH,所有的MAIN(a, v)在预
编译的时候就被替换为PROG(a, v),在每个源文件中,由于对PROG的独
特的定义,PROG又会被替换成一个独特的函数名称。
如在ca.c文件中,MAIN就会被替换成这样:
int ca_main(int, char **)
在openssl.c中,就可以以ca_main子程序的方式来使用这个ca程序。
其他:
这里还出现了一个关于NON_MAIN的预编译选项。它的出现是由于在程序
中有一些都要使用到的变量,无论是在大程序还是在小程序中,像上面
的 config 和 bio_err。
在编译小程序时,由于没有定义 MONOLITH 和 NON_MAIN,在apps.h中
对 config 和 bio_err 的定义就会是这样:
CONF *config=NULL;
BIO *bio_err=NULL;
这个时候注意到 apps.h 是 apps.c 的头文件,如果不做任何处理的话
我们将得到在多个obj文件中重复定义的错误,所以在apps.c中#include
被写成这样:
#define NON_MAIN
#include "apps.h"
#undef NON_MAIN
这时对于apps.c来说,config 和 bio_err 的定义就是:
extern CONF *config;
extern BIO *bio_err;
如果是编译大程序,由于 MONOLITH 已被定义,config 和 bio_err 在
apps.h中定义都是 extern 型的,这两个变量被定义在openssl.c源文
件中:
#ifdef MONOLITH
CONF *config=NULL;
BIO *bio_err=NULL;
#endif
总结:
就像在开头说的那样,如果我们独立的编写一些小程序,在最后会合并
到一个大程序中的话,我们就可以使用这样的方式。但我觉得也有不好
的地方,int (*func)(int argc, char *argv[])这样的函数接口似乎不
是很妥当。
看情况用着吧。 ;-)