hdqqq

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  35 随笔 :: 0 文章 :: 104 评论 :: 0 Trackbacks

#

       上一篇讲到了根据一个typelist实现一个结构,这个结构带有typelist中所有类型的成员,同时,可以通过Field0,Field1等接口访问和赋值.在这个基础上,我们可以构建对应一条记录的结构data_row,

二.一条记录

#define ROW_NO_CHANGE 0
#define ROW_ADD 
1
#define ROW_UPDATE 
2
#define ROW_DELETE 
3

template
<typename _tlist>
class data_op_record_row : 
public struct_mem<_tlist>
{
public:
    enum _enum_RowState {
        _en_Row_NoChange 
= ROW_NO_CHANGE,    //未修改
        _en_Row_Add 
= ROW_ADD,            //新增记录
        _en_Row_Update 
= ROW_UPDATE,        //更新
        _en_Row_Del 
= ROW_DELETE,        //删除
    } m_en_State;
public:
    void SetState(
int newstate) {
        
if (m_en_State != newstate) {
            
if (newstate == _en_Row_NoChange || 
                newstate 
== _en_Row_Add || 
                newstate 
== _en_Row_Update || 
                newstate 
== _en_Row_Del) 
            {
                m_en_State 
= (_enum_RowState)newstate;
            }
        }
    }
public:
    data_op_record_row () : m_en_State(_en_Row_NoChange) {}
    ~data_op_record_row (){}
protected:
private:
};
上面的类增加了一个枚举,标识这条记录当前的状态,在记录集中,将根据记录的状态进行相关的操作.这个其实类似与.net中的DataRow,不过.net中的DataRow可以用wizzard生成需要的类,而这里是用模板生成的.

三.数据类型转换
      数据库中的表对应的字段有不同的数据类型,ADO操作接口中用不同的数据类型与之对应,其中Field接口的GetType就是返回字段类型的,但是ADO的GetValue返回的是_variant_t类型,为了实际业务的需要,还需要转换成不同的类型,因此,需要对_variant_t类型进行转换.为此需要提供模板转换函数

template <typename _type>
void DbData_Change(_type
& ret, _variant_t& field)
{
   AfxMessageBox(
"未定义的数据转换");
}


template 
<>
void DbData_Change
<int>(int & ret, _variant_t& field)
{
    ret 
= field.lVal;
}

template 
<>
void DbData_Change
<std::string>(std::string& ret, _variant_t& field)
{
    _bstr_t temp;

    
if (field.vt != VT_NULL) {
        temp 
= field.bstrVal;
        ret 
= temp.operator const char*();
    }
}

template 
<>
void DbData_Change
<bool>(bool& ret, _variant_t& field)
{
    ret 
= (field.boolVal == (short)0xFFFF ? TRUE : FALSE);
}

template 
<>
void DbData_Change
<double>(double& ret, _variant_t& field)
{
    
if (field.vt != VT_NULL) {
        
//ret = field.cyVal;
        ret 
= field.dblVal;
    }
else {
        ret 
= 0;
    }
}

上面的模板函数的功能是从_variant_t转换到某中数据类型,对于其它类型还可以进行扩充,对于没有进行特化的函数,编译器会使用缺省模板,在运行时候就会出现提示.有了上面的函数,现在我们需要一个数据类型的封装类,使得被封装的类型可以自动进行从_variant_t类型的需要类型的转换,所以有了下面的封装类.
//数据库数据类型封装
template 
<typename _type>
class _db_data_wrapper
{
public:
    _type
& Value() {
        return m_Data;
    }

    
const _type& operator =(const _type& value) {
        m_Data 
= value;
        return value;
    }

    _db_data_wrapper
& operator = (const _db_data_wrapper& other) {
        
if (this != &other) {
            m_Data 
= other.m_Data;
        }
        return 
*this;
    }

public:
    virtual void GetDbValue(_variant_t
& field_value) {
        DbData_Change(m_Data, field_value);
    }

public:
    _db_data_wrapper(){}
    _db_data_wrapper(
const _type& value) : m_Data(value) {}
    ~_db_data_wrapper(){}
private:
    _type m_Data;
};

typedef _db_data_wrapper
< int > DB_INT;
typedef _db_data_wrapper
< std::string > DB_STRING;
typedef _db_data_wrapper
< bool > DB_BOOL;
typedef _db_data_wrapper
< double > DB_DOUBLE;



上面的代码预定义了几种常用的数据类型,这个数据的封装类支持 = 操作符,因此可以直接用被封装的数据对其赋值.象下面
int i = 4;
DB_INT di;
di 
= i;
= di.Value();


同时通过成员函数GetDbValue(_variant_t& field_value), 支持从_variant_t转换为自身封装的类型.

现在,可以用上面的数据类型构建记录结构了

typedef data_op_record_row< TYPELIST_2(DB_INT,DB_STRING) > my_DataRow;

在上面的my_DataRow类型中,有两个成员Field0, Field1,类型分别为 DB_INT,DB_STRING, 支持_variant_t类型转换.

当然,用wrapper对数据进行封装在实际的使用中毕竟有些麻烦, 如数据必须通过 Value() 函数来取得,如果直接使用象 int, std::string 等类型作为 记录结构的成员,也可以实现_variant自动转换,但是需要在上一层的记录集类中加入相关的转换操作,实现起来比较麻烦,所以我这里选择了对数据进行封装.


 

posted @ 2007-01-22 17:33 hdqqq 阅读(1209) | 评论 (1)编辑 收藏

     c++在数据库开发这种需要进行快速开发的地方一直是以效率低下著称,borland 的c++ build 依赖vcl提供的组件勉强可以实现,但是由于用的是pascal的东西,根基不行,一直叫不响.再看看现在流行的数据库,sql server 和mysql 等虽然提供本地开发的头文件和库,但是对于一些可能使用不同数据库的应用来说,选择特定某种数据库开发显然是不妥,因此,象ado这种数据操作接口大行其道.这又给用c++开发带来了麻烦,象vb等工具可以自动转换variant类型,但是在vc使用的时候却很麻烦.网上那些使用ado接口的c++的例子,大多数都从#import 那个dll开始, 然后就是繁琐的创建instance,打开记录集,最后还要进行一个variant到c++类型的转换,确实是够麻烦的,难怪效率低下.
 
    在很多情况下,一些数据查询和数据操作往往是在开发的时候就确定下来了,比如说你有个用户表要操作,你在开发的时候就知道这个表中的所有字段名称和字段类型,但是你用ado,你却还是要和繁琐的variant打交道,把它转换为你想要的数据类型. 如果能实现一个类,在知晓数据表字段类型的情况下,可以方便地使用c++数据类型,并且可以进行诸如插入,删除,更新等操作,那就方便多了.  这就是本文想实现的目标.  但是对于那些在运行时候才确定的数据操作,如用户输入一个 sql 查询,然后再来进行操作,对于象c++ 这种强类型的语言来说,可能除了使用 variant别无他法, 对于这方面,本文没有给出解决办法.

本文中的代码在vc6下编译通过
需要的库 loki for vc6, boost

一. 构造记录结构

   通常来说,数据集由一条条的记录组成,记录下有字段,记录是数据操作的基本单元.照c++的习惯,最好是一条记录一个结构,字段就是这个结构的成员,然后用列表或者vector组合一下就是记录集了.但是一条记录的字段是有可能变动的,还好,有loki 的 typelist.

 

 1 #if !defined(INCLUDE_40697E96_B6DE_449D_A516_B0376650A488)
 2 #define INCLUDE_40697E96_B6DE_449D_A516_B0376650A488
 3 
 4 #if _MSC_VER > 1000
 5 #pragma once
 6 #endif
 7 
 8 #include <typelist.h>
 9 #include <functor.h>
10 #include <boost/preprocessor/dec.hpp>
11 
12 #define HELP_2(a , b) a(b)
13 
14 #define MEM_STRUCT_MAKE_IMPL(n) template <typename _tlist> \
15 struct In : public _str_impl_help<n>::template In<typename _tlist::Tail> \
16 { \
17     typedef _str_impl_help<n>::template In<typename _tlist::Tail> _Base; \
18     enum {    en_member_count = _Base::en_member_count+1, }; \
19     typedef typename ::Loki::TL::TypeAt<_tlist, 0>::Result _type##n; \
20     _type##n m_P##n; \
21     __declspec(property(get = GetF##n, put = PutF##n)) \
22     _type##n Field##n; \
23     _type##n GetF##n() { return m_P##n; } \
24     void PutF##n(const _type##n val) { m_P##n = val; } \
25 }; \
26 }
27 
28 #define MEM_STRUCT_MAKE(n) template <> \
29     struct _str_impl_help<n> { \
30     HELP_2(MEM_STRUCT_MAKE_IMPL, BOOST_PP_DEC(n))
31     
32 
33 namespace impl_help
34 {
35     template <int _p>
36     struct _str_impl_help;
37 
38     template <>
39     struct _str_impl_help<0> {};
40     template <>
41     struct _str_impl_help<1> {
42         template <typename _tlist> 
43         struct In {
44             enum {
45                 en_member_count = 1,
46             };
47 
48             typename ::Loki::TL::TypeAt<_tlist, 0>::Result m_P0;
49 
50             __declspec(property(get=GetF0, put=PutF0))
51             typename ::Loki::TL::TypeAt<_tlist, 0>::Result Field0;
52 
53             typename ::Loki::TL::TypeAt<_tlist, 0>::Result GetF0() { 
54                 return m_P0; 
55             }
56 
57             void PutF0(const typename ::Loki::TL::TypeAt<_tlist, 0>::Result val) {
58                 m_P0 = val;
59             }
60         };
61     };
62 
63     MEM_STRUCT_MAKE(2);
64     MEM_STRUCT_MAKE(3);
65     MEM_STRUCT_MAKE(4);
66     MEM_STRUCT_MAKE(5);
67     MEM_STRUCT_MAKE(6);
68     MEM_STRUCT_MAKE(7);
69     MEM_STRUCT_MAKE(8);
70     MEM_STRUCT_MAKE(9);
71     MEM_STRUCT_MAKE(10);
72     MEM_STRUCT_MAKE(11);
73     MEM_STRUCT_MAKE(12);
74     MEM_STRUCT_MAKE(13);
75     MEM_STRUCT_MAKE(14);
76     MEM_STRUCT_MAKE(15);
77 }
78 
79 template <typename _tlist>
80 struct struct_mem : public impl_help::_str_impl_help< ::Loki::TL::Length<_tlist>::value >:: 
81     template In< ::Loki::TL::Reverse<_tlist>::Result >
82 {
83 };
84 
85 
86 #endif //!defined(INCLUDE_40697E96_B6DE_449d_A516_B0376650A488)

上面是模板实现根据指定typelist,生成拥有相应成员的结构.

typedef struct_mem< TYPELIST_6(DB_STRING, DB_STRING, DB_STRING, DB_STRING, DB_STRING, DB_STRING) > CustomerRow; 就可以声明一个有6个成员的结构了.
上面的代码使用template的特化到有15个成员的结构,全部写出来的话,重复而且麻烦,所以使用了宏来帮助生成.


 

posted @ 2007-01-19 10:35 hdqqq 阅读(993) | 评论 (0)编辑 收藏

?:操作符是一个条件赋值的操作符号,常用来对变量进行条件赋值如:

int i = 1, j = 2;
int c_max = ( i > j ? i : j );

不过今天看了网上的一段代码,是这样用的

(i->second.left ? file.leechers : file.seeders)--;

上面的三个都是变量,也可以编译通过,所以写了段代码试了一下

 1 void show_1(int val)
 2 {
 3     cout << "function show_1 called!" << endl;
 4 }
 5 
 6 
 7 void show_2(int val)
 8 {
 9     cout << "function show_2 called!" << endl;
10 }
11 
12 
13 void quest_test()
14 {
15     int c = 0;
16     int a = 1, b = 2;
17     (c++ ? a : b)--;
18     cout << a  << " and "  << b << endl;
19     (c ? a : b)++;
20     cout << a  << " and "  << b << endl;
21     (c ? show_1 : show_2)(100);
22 }
23 
24 
25 最后的输出是
26 1 and 1
27 2 and 1
28 function show_1 called!


最怪的是?:操作符号,居然也可以用在函数上.

(c ? show_1 : show_2)(100);

其实等同于

if (c)
  show_1(100);
else
  show_2(100);

不过简练了很多.

posted @ 2006-12-29 17:06 hdqqq 阅读(1268) | 评论 (3)编辑 收藏

unix系统下的banner是用于显示点阵字体的程序cygwin下有类似的程序可以在windows下跑,但是不支持中文.

所以自己写了一个windows下的类似程序,自己建一个控制台工程(需支持mfc)后,把下面的代码复制一下就可以了.同时,新年快到了,祝大家:

     #      ##       ##            #    ##         #    #### 
  ###### ###        #########      # #   #         #######   
    # #  #        ##   ##        # # ########      #   ##    
  ###### #######   ##########    # #     #  #     ##   ##    
 #  ##  ## ## #    ##  ##        # #     ####     ############
  ###### # ##    ###############   # ##########      # ###   
   ### ### ##    ##    ##  ####    #    # #  #      ## ## ## 
  #### ##  ##          ##          #   ## ##      ###  ##  ####
 #  ##  #  ##          ##          # ###   ##    #   # ##    ##
            #          ##          ##                 ##      

      8  88            8               8  8                88  
   8888888888     88888888888      88  8 88       88888    88  
      8  8         888888888       8   8          8 8 8 88888888
  8888 888888       8888888        888888888      8 8 8    8888
     888  88        88   88           88888       8 8 8   888  
   88  8   888        8888            88 88       8 8 8  8888  
8888 8 8888 888  88888888888888     88  88        888 8888 88  
    8  88 88 8      88888888     8888  88 888      8888    88  
   8 888 8 8        88    88        8888   8888  888  88 8888  
      88            88888888                 8             8   

使用方式

wbanner [-c 填充字符] [-f 字体名称] [-s 字体大小] 显示文本

/////////////////

//  wbanner_6.cpp : Defines the entry point for the console application.
//

#include 
" stdafx.h "
#include 
" wbanner_6.h "

#ifdef _DEBUG
#define  new DEBUG_NEW
#undef  THIS_FILE
static   char  THIS_FILE[]  =  __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////// //
//  The one and only application object

CWinApp theApp;

using   namespace  std;


#define  BMP_WIDTH    100
#define  BMP_HEIGHT    30

void  ParseArg(CString &  info, CString &  fill_str,CString &  font_name,  int &  font_size,  int  argc,TCHAR *  argv[])
{
    
int  i;
    
for  (i  =   1 ; i  <  argc; i ++ ) {
        
if  (strcmp(argv[i],  " -c " ==   0   &&  i  <  argc) {
            fill_str 
=  argv[ ++ i];
            
continue ;
        }
        
if  (strcmp(argv[i],  " -f " ==   0   &&  i  <  argc) {
            font_name 
=  argv[ ++ i];
            
continue ;
        }
        
if  (strcmp(argv[i],  " -s " ==   0   &&  i  <  argc) {
            font_size 
=  atoi(argv[ ++ i]);
            
if  (font_size  <=   120
                font_size 
=   120 ;
            
continue ;
        }

        info 
=  argv[i];
        
break ;
    }
}

void  ShowBanner(LPCTSTR fill_str, LPCTSTR info, LPCTSTR font_name,  int  font_size)
{
    CFont lfont;
    CDC ldc;
    CBitmap lbmp;
    ldc.CreateCompatibleDC(NULL);
    lbmp.CreateCompatibleBitmap(
& ldc, BMP_WIDTH, BMP_HEIGHT);
    CBitmap
*  pold  =  (CBitmap * )ldc.SelectObject( & lbmp);
    
    lfont.CreatePointFont(font_size, font_name, 
& ldc);
    
    CFont
*  poldfont  =  (CFont * )ldc.SelectObject( & lfont);
    
    CRect lrect(
0 0 , BMP_WIDTH,BMP_HEIGHT);
    
    ldc.FillSolidRect(
0 , 0 , BMP_WIDTH, BMP_HEIGHT, RGB( 255 , 255 , 255 ));
    ldc.DrawText(info, 
& lrect, DT_LEFT);
    
    BITMAP bmp_head;
    
    lbmp.GetBitmap(
& bmp_head);
    
    
    DWORD bufsize 
=  bmp_head.bmWidthBytes * bmp_head.bmHeight;
    
char *  buf  =   new   char [bufsize];
    
    memset(buf, 
0 , bufsize);
    
    DWORD get_ret 
=  lbmp.GetBitmapBits(bufsize, ( void * )buf);
    
    
int  i,j;
    
if  (get_ret  !=   0 ) {
        
char  ret[ 2 =  {  13 10 };
        CString 
out [ 2 =  {fill_str,  "   " };
        
for  (i  =   0 ; i  <  bmp_head.bmHeight; i ++ )
        {
            
int  charcount  =   0 ;
            
for  (j  =   0 ; j  <  bmp_head.bmWidth; j ++ ) {
                
int  offset  =  bmp_head.bmWidthBytes * i + j / 8 ;
                
char  cur;
                cur 
=  buf[offset];
                
char  tt  =  cur  &  ( 0x80   >>  (j  %   8 ));
                CString temp;
                
if  (tt  ==   0 ) {
                    temp 
=   out [ 0 ];
                }
else  {
                    temp 
=   out [ 1 ];
                }
                cout 
<<  (LPCTSTR)temp;
                charcount
++ ;
            }
            cout 
<<  endl;
        }
    }
        
    ldc.SelectObject(pold);
    ldc.SelectObject(poldfont);
    delete [] buf;
}

void  PrintUsage( int  argc, TCHAR *  argv[])
{
    cout 
<<   " not enough arguments "   <<  endl;
    cout 
<<   " Usage: "   <<  endl;
    cout 
<<  argv[ 0 <<   "  [-c #] [-f font_name] [-s font_size] A string to print "   <<  endl;
}

int  _tmain( int  argc, TCHAR *  argv[], TCHAR *  envp[])
{
    
int  nRetCode  =   0 ;

    
//  initialize MFC and print and error on failure
     if  (AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(),  0 ))
    {
        
//  TODO: change error code to suit your needs

        CString info 
=   " wbanner " ;
        CString font_name 
=   " 宋体 " ;
        CString fill_str 
=   " # " ;
        
int  font_size  =   120 ;
        
        
        
if  (argc  <   2 ) {
            PrintUsage(argc, argv);
        }
else  {
            ParseArg(info, fill_str, font_name, font_size, argc, argv);
            ShowBanner(fill_str, info, font_name, font_size);
        }
    }
else  {
        cerr 
<<  _T( " Fatal Error: MFC initialization failed " <<  endl;
        nRetCode 
=   1 ;
    }
    
return  nRetCode;
}


posted @ 2006-12-22 10:13 hdqqq 阅读(1131) | 评论 (2)编辑 收藏

  今天写了一个ace 的proactor的测试程序,代码是在windows下编辑的,在windows下测试成功后,将代码传到一台linux机器上进行测试,配置了相关的configure.in和Makefile.am文件后,用autoconf,automake和configure生成makefile然后make开始编译,但是程序报错,开始以为是ace的配置的问题,重新设置了ace的linux下的配置头文件,并重新编译,不行,然后重新设置configure.in文件和Makefile.am文件,还是不行,搞了半天,最后仔细看了gcc的报错信息,是有一些头文件无法包含,看了编译的参数, incldue设置正确, 最后终于发现,原来是因为在windows下编辑的代码,头文件用了小写名称,导致在linux下包含的头文件找不到,这个是在类unix下开发应该注意的小细节,一个疏忽,往往容易阴沟里翻船.特此记录一下.
posted @ 2006-12-11 16:44 hdqqq 阅读(702) | 评论 (0)编辑 收藏

      今天在网上下载了一个c++的代码,项目文件是sln的文件.
我双击打开,vs2003报告说,这个项目文件是高版本的vs生成的,目前不支持,搞了半天这个项目文件是vs2005生成的,这种高级货我当然没用过,装vs2005或者重新构建项目工程都比较麻烦,所以从项目文件上着手,看看是否可以修改一下,让我的vs2003可以用. 随便找了一个vs2003生成的sln文件,和vs2005生成的看看,都是类似xml的文件,差别只是一个版本号不同,把两个文件修改为vs2003的8.0 sln版本,vs2003还是不认.估计是vcproj的差别,然后查看2003和2005vcproj文件的差别,也差不多,只是版本号上的差别,所以想办法实验了一下, 把 vs2005的sln文件删除,用文本编辑程序打开vcproj文件,vs2005生成的文件,版本号是8,00 我直接改成了vs2003的7.10 然后保存vcproj文件,再双击打开,vs2003通过了,可以直接编译运行了,vs2003还会自动生成新的sln文件.
posted @ 2006-12-09 00:27 hdqqq 阅读(2420) | 评论 (0)编辑 收藏

;一个汇编版本的 hello world
;test.asm
;a hello world program with asm
.386P
.model FLAT

include listing.inc

INCLUDELIB LIBCD
INCLUDELIB OLDNAMES

PUBLIC _main
PUBLIC szHelloWorld
EXTERN _printf:NEAR


CONST SEGMENT
 szHelloWorld DB 'Hello World!', 0aH, 00H
CONST ENDS

_TEXT SEGMENT

_argc$ = 8
_argv$ = 12
_main PROC NEAR
 push OFFSET FLAT:szHelloWorld
 call _printf
 add esp, 4
 xor eax, eax 
 ret 0
_main ENDP
_TEXT ENDS

END
 
;编译命令
;ml.exe    /c   /coff    test.asm
;link /out:test.exe /subsystem:console kernel32.lib test.obj

posted @ 2006-09-21 14:25 hdqqq 阅读(361) | 评论 (0)编辑 收藏

STL, Loki,Boost Functor 比较之 Boost ( )

       在这一部分中 , 要讨论的是 Boost 库中的 Function 的有关功能 , 于前面两篇不同的是 ,Boost 库的规模相对于 Loki STL 来说 , 在规模上大了很多 , 这篇文章中讨论的是 boost 中的 functor 部分 , 写的不好之处 , 欢迎提出意见 . 写作本文使用的是 Boost 1_33_1 版本 , 同时参考了 Boost 文档的 function 部分的说明 .

 

写在前面

Boost Function 功能中 , 用到了 Boost Preprocessor, 在这部分中 Boost 提供的宏预处理功能是很强大的 , 主要的宏功能有 重复生成 (BOOST_PP_REPEAT_FROM_TO), 条件判断 (BOOST_PP_IF), 连接 (BOOST_PP_CAT), 数值比较 (BOOST_PP_GREATER), 参数枚举 (BOOST_PP_ENUM_PARAMS) , 使用这些宏 , 可以按照自己的需要用宏生成模板类或者代码 , 实在是一个很有效而且很创新的功能 , 可以说把预处理器的功能用到了登峰造极的地步 . 不过 , 代价是要花更多的时间在编译上 , 我有一个 18000 行代码的工程 , 在一个头文件中使用了 Preprocessor 产生一些模板代码后 , 编译时间从原先的 4 分钟一下子升到了 8 分多秒 ( 我的机器比较老 ), 最后不得不写了个功能 Proxy , 隔绝 cpp 文件对该头文件的依赖关系才缩短了编译时间 .

TypeTraits typetraits 的功能是在给定一个数据类型后 , 通过 c++ 的模板能力 , 来取得这个关于这个数据类型的相关信息 . Loki 库中 , 也提供了 TypeTrait 功能 . 常用的有 判断是否为指针 , 判断是否为常量 , 判断是否为引用 , 判断是否为数值等 . 在创建模板类或者函数的时候 , 有时候需要根据模板参数的类型对模板进行特化 , 这是一个很重要的辅助功能 ,boost 中也有 typetrait 功能 , functor 生成的过程中 , 也使用了一些 typetrait 的功能 .

 

 

Boost 的的 Functor 的头文件位于 <boost/function.hpp> 文件中 , 有一个很重要的宏

BOOST_FUNCTION_MAX_ARGS 用于 定义 boost 的预处理器展开的 Functor 最多的参数个数 , 缺省的定义为

#define   BOOST_FUNCTION_MAX_ARGS   10

如果有需要扩充 Functor 的参数个数 , 可以在包含 Boost Functor 头文件之前 , 自己定义这个宏的数值 , 但是 , 最多可以到 50, 超过这个数值后 , 需要手工修改 <boost/function/detail/maybe_include.hpp> 中的代码 , Functor 可以使用的参数再进行扩充 .

 

Boost Functor 的展开

       Boost 中使用了预处理元编程提供的叠代头文件的功能 , 反复叠代 <boost/function/function_template.hpp>, 最终生成使用所需要的模板类

 

boost::function < 返回值 ( 参数 [, 参数 ]…)>, 用户可以使用编译器的 /P( 微软 c++ 编译器 ),  -save-temps(gcc 编译器 ) 开查看宏展开后的文件 .

 

 

 

有关 STL Loki 中的 Functor 的前面两篇位于我的另外一个 blog

http://blog.csdn.net/hdqqq/archive/2006/02/07/593877.aspx

http://blog.csdn.net/hdqqq/archive/2006/01/25/588348.aspx

posted @ 2006-09-13 21:39 hdqqq 阅读(3904) | 评论 (1)编辑 收藏

/*
 这几天在编译firefox,顺便学一下unix下的shell的脚本编写,unix下的管道和工具
结合起来用的话,功能确实强大.写了个测试的脚本,功能是把c/cpp/h文件中所有包含的头文件
找出来,支持通配符.
 可以把下面的文字复制到某个文件,然后另存为.sh后缀的文件放到/bin目录下就可以运行了,在
cygwin环境下测试通过.
*/

## list_head.sh

ARR_NUM=1

if [ $# -lt $ARR_NUM ]
then
echo "使用方式:"
echo "$0 文件名"
echo "文件名: C/CPP/H 文件 或 通配符 *.c(*.cpp)"
else

cat $@ | grep include | grep \# | sort | uniq | awk -Finclude '{ print $2 }' | tr -d \" | tr -d \' | tr -d \< | tr -d \> | sort | uniq | awk '{ print $1 }'

fi

exit 0

posted @ 2006-09-06 17:18 hdqqq 阅读(456) | 评论 (0)编辑 收藏

前几天心血来潮 , 想自己编译一个 firefox 试试看 , 折腾了好几天 , 终于完成了 .

写篇文章总结一下 .

我编译的环境 :

1.       VC6 + sp5

2.       firefox 编译需要的辅助工具 wintools.zip

3.       cygwin 环境

 

准备工作 :

1.       下载 firefox 程序代码,在 mozilla 的站点上可以下载到,我编译的是 firefox 1.5.0.6 版本

2.       下载编译需要的 wintools.zip 工具 ,1.73MB 大小 , 其中带有 glib libidl , 在下载解压缩后 , 建立一个环境变量 MOZ_TOOLS 到某个目录 , 然后进入解压缩后的 windows 目录 , 运行 install.bat 文件 , 安装相关需要的文件 .

3.       安装 cygwin 环境 , 一个 window 下的类 unix 平台 , 这里需要注意的是 , 最新的 cygwin , 安装的 make 版本是 3.81 , 而编译 firefox 需要的是 3.80 版本的 make, 解决的方法是到 cygwin 的某个 ftp 镜像站点上去下一个 3.80 版本的文件 , 安装到 cygwin 安装目录下的 /bin 目录下就可以了 .

其中编译 firefox 需要的基本工具

ash -- UNIX-like command line interpreter shell (Base category)

coreutils -- GNU core utilities (includes fileutils, install, sh-utils, and textutils) (Base category)

cvs -- concurrent versions system (Devel category)

diffutils -- file comparison utility (Base category)

findutils (Base category)

gawk -- pattern matching language (Base and Interpretors categories)

grep -- text search tool (Base category)

libiconv -- character set conversion (Devel category)

make 3.80 (not 3.81!) -- dependency analyzer for software builds (Devel category)

patchutils -- a small collection of programs that operate on patch files (Devel category)

perl -- a scripting language used to control parts of the build (Interpreters category)

sed -- a search and replace language (Base category)

unzip -- zip file extraction (Archive category)

zip -- zip file creation (Archive category)

可以在 cygwin 命令窗口中输入相关命令检测是否安装了相关的程序 ., 其实如果下载了 firefxo 源代码的话 , cvs 中的都不是必须的 .

4.       安装 vc6 + sp5, 编译 firefox 1.5.0.6, 推荐的是 vc6 cpp 编译器 . vs6 安装后 , 会自动设置相关的 path,include lib 环境变量 . 有一个需要注意的是 , vc6 link.exe cygwin 中的 link.exe 是相同的名字 , 为了避免在编译的时候 , 调用错误的 link 执行文件 , 可以把 cygwin/bin 中的 link.exe 改名为 glink.exe 避免冲突 . Vs sp5 补丁也需要打一下 , 否则 , 生成的 xpldl.exe(firefox 用来编译 idl 文件的工具 ) 在编译 idl 过程中会报错 .

5.       配置文件

在环境和编译工具准备好后 , 解压缩 firefox 的代码 , 然后在 firefox 代码目录的 mozilla 目录下 , 建立一个名为 .mozconfig 的文件 , 并在其中编辑文本

. $topsrcdir/browser/config/mozconfig

ac_add_options --enable-optimize

ac_add_options --disable-debug

ac_add_options --enable-static

ac_add_options --disable-shared

ac_add_options --disable-test

开工

上面所有工作完成之后 , 启动 cygwin 命令窗口 , 进入 firefox 代码的 mozilla 目录

输入 make –f client.mk build 命令开始编译 , 一切顺利的话 , 几十分钟后 , 就会有一个 firefox 的执行文件生成到 mozilla/dist/bin 目录下 .

需要注意的是 , 在生成一个 test 的模块的时候 , 会报一个 jsint 类型未定义 , 这个无关紧要 , 因为 firefox 已经生成了 , 这是一个测试模块 , 我的解决方法是 , 打开那个出错的cpp文件,加入

#ifdef   _MSCVER

typedef  int  int32;

#endif

然后再编译就可以了 , 所谓自动动手 , 丰衣足食 , 有的时候 , 实在不行的话 , 需要把 firefox 的代码自己动手改一下 .

 

 

posted @ 2006-09-03 18:14 hdqqq 阅读(1531) | 评论 (0)编辑 收藏

仅列出标题
共4页: 1 2 3 4