C++快速入门 (九) 可变参数和链接库

一 可变参数

(1). 实现可变参数
C++ 用 <...> 表示这里可变(任意多个)的参数,我们又知道 参数是又右向左一次入栈的,有了这两个条件只要知道 可变参数的类型,我们就可以实现可变参数

int  Add( int   size, ... )
{
      int  sum = 0;
      int  *p = & size  + 1;
      while  (   size  )
    {
        sum += (*(p++) );
        --   size  ;
    }
      return  sum;
}

其中 size 表示可变参数的个数,

(2). 运行库实现的可变参数
其实在运行库( stdarg.h)  里已经提供了类似的宏实现的可变参数
  • va_start(可变参数前的首个参数, 可变参数个数) -- 设置起始位置
  • va_arg(可变参数前的首个参数,可变参数类型) -- 返回当前可变参数,并指向下一个
  • va_end(可变参数前的首个参数) -- 结束可变参数访问

int  Add( int   size, ... )
{
      int  sum = 0;
      va_list  ap;
      va_start(ap,   size  );
      while  (   size  )
    {
        sum +=   va_arg  (ap, int  );
        --   size  ;
    }
      va_end(ap);
      return  sum;
}




二 链接库

(1). 什么是库
链接库可分为 库 和 链接(方式)两部分,当开发一个较大的 项目 或该 项目 有多人参与时,将该项目按照某种条件分为多个部分(库),并且每个 部分(库) 可以单独编译测试,在使用时多个部分(库)之间只需进行简单调用(链接)即可, 这样开发 效率 会大幅提升. 而且也可简化以后程序升级和维护工作。
(2). 链接方式
库按链接方式可分为  静态链接库 和 动态连接库

三 静态链接库

(1). 什么是静态链接库
静态链接库本身可单独编写,编译和测试,但当整个项目需要发布时,静态链接库会作为目标文件的一部分编译在一起。通常后缀为 ".lib" .
(2). 示例

// a.cpp -> a.lib
// $ cl /c a.cpp
// $ lib a.obj /out:a.lib
#pragma  once
#define  WIN32_LEAN_AND_MEAN
#include  <windows.h>


BOOL  APIENTRY DllMain(  HMODULE  hModule ,
                       DWORD    ul_reason_for_call ,
                       LPVOID  lpReserved
                      )
{
     switch (  ul_reason_for_call )
    {
     case  DLL_PROCESS_ATTACH:
     case  DLL_THREAD_ATTACH:
     case  DLL_THREAD_DETACH:
     case  DLL_PROCESS_DETACH:
         break ;
    }
     return  TRUE ;
}
__declspec ( dllexport )  double Add (  double  a ,  double  b )
{
     return  a +  b ;
}
__declspec ( dllexport )  double Sub (  double  a ,  double  b )
{
     return  a -  b ;
}
__declspec ( dllexport )  double Mul (  double  a ,  double  b )
{
     return  a *  b ;
}
...........................................

// b.cpp -> b.exe
// $ cl /c b.cpp
// $ link b.obj a.lib
#include  <iostream>
#include  <windows.h>

using  namespace std;

__declspec ( dllexport )  double Sub (  double a,  double b);

int  _tmain ( int  argc_TCHARargv [])
{

     cout << Sub(5.0,5.0);
     return 0;
};
  




四 动态链接库

(1).  什么是动态链接库
动态 链接库本身可单独编写,编译和测试,当整个项目需要发布时,动态链接库会作为单独文件独立存储,当虚调用动态链接库中的代码时,需要使用特定方法先将其加载进内存,一般后缀为“.dll”. 
(2). 示例

// a.cpp -> a.lib
// $ cl /LDd a.cpp
#pragma  once
#define  WIN32_LEAN_AND_MEAN
#include  <windows.h>


BOOL  APIENTRY DllMain(  HMODULE  hModule ,
                       DWORD    ul_reason_for_call ,
                       LPVOID  lpReserved
                      )
{
     switch (  ul_reason_for_call )
    {
     case  DLL_PROCESS_ATTACH:
     case  DLL_THREAD_ATTACH:
     case  DLL_THREAD_DETACH:
     case  DLL_PROCESS_DETACH:
         break ;
    }
     return  TRUE ;
}
extern  "C"  __declspec ( dllexport )  double Add (  double  a ,  double  b )
{
     return  a +  b ;
}
extern "C"  __declspec ( dllexport )  double Sub (  double  a ,  double  b )
{
     return  a -  b ;
}
extern "C"  __declspec ( dllexport )  double Mul (  double  a ,  double  b )
{
     return  a *  b ;
}
............

// b.cpp -> b.exe
// $ cl  b.cpp
#include  <iostream>
#include  <windows.h>

using  namespace std;
typedef double (*func) ( doubledouble );

int  _tmain ( int  argc_TCHARargv[])
{
      func pFunc;
      HINSTANCE hinstLib =  LoadLibraryA"a.dll");
      if (hinstLib ==  NULL)
     {
         cout <<  "动态库加载失败" << endl;
          return 1;
     }
     pFunc = (  func) GetProcAddress(hinstLib, "Add" );
      if (pFunc ==  NULL)
     {
         cout <<  "函数加载失败" << endl;
          FreeLibrary(hinstLib);
          return 1;
     }
     cout << pFunc(5.0,5.0);
      FreeLibrary(hinstLib);
     return 0;
};


说明:
由于 C++的默认函数调用方式为 __stdcall ,而这种调用方式在编译时函数会被改名,
所以要用 < extern "C" > __cdecl 而 C 默认方式

(3). 通过植入桩代码实现动态链接
上面的代码在调用动态链接库前,调用方对库是“一无所知”的,必须在调用时先手动加载动态库(dll)。而另一种编译方式可以预先在 调用方链接时插入桩代码,从而可以直接调用 dll 中的导出函数, 这里我们要用到动态库的 lib 文件。编译命令如下

$ cl /LD a.cpp
$ cl /c b.cpp
$ link b.obj a.lib


(4). 编写动态链接库时注意事项
编写动态库时,不要在 DLL里申请内存,而在 DLL 外释放内存。不要公开重载方法 和 慎用 C++标准库 STL。

-

<原创文章 转载请注明出处 http://blog.csdn.net/meiwm 谢谢>


作者:meiwm
出处: http://blog.csdn.net/meiwm
本文为原创,本文版权归作者所有。欢迎转载,但请务必保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。

-
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值