BCB中DLL的创建和调用

BCB 专栏收录该内容
36 篇文章 1 订阅

摘自:http://blog.csdn.net/ww425/article/details/306500

一 编写动态链接库DLL


DLL简称动态链接库,是Windows中程序的重要组成部分。想象一下,一个程序需要多人共同完成开发,怎么个共同法?这时我们就要考虑把程序分为好几个模块,团队每一个成员开发一个模块。问题来了:如何将模块组合并成一个完整系统?还有,我们开发的软件需要不断升级,如何升级?难道每次非得把整个工程重新编译一次再发布给用户吗?解决这些问题的科学办法,就是开发动态链接库DLL。
现在以开发myDLL.dll动态链接库为例,讲讲BCB中开发动态链接库的方法。
1、新建立一个工程:File-New-Other...在New卡中选择DLL Wizard
2、将工程存为myDLL.bpr
3、在myDLL.cpp中写接口代码:
---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#pragma hdrstop
---------------------------------------------------------------------------
   Important note about DLL memory management when your DLL uses the
   static version of the RunTime Library:

   If your DLL exports any functions that pass String objects (or structs/
   classes containing nested Strings) as parameter or function results,
   you will need to add the library MEMMGR.LIB to both the DLL project and
   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
   if any other projects which use the DLL will be performing new or delete
   operations on any non-TObject-derived classes which are exported from the
   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
   the file BORLNDMM.DLL should be deployed along with your DLL.

   To avoid using BORLNDMM.DLL, pass string information using "char *" or
   ShortString parameters.

   If your DLL uses the dynamic version of the RTL, you do not need to
   explicitly add MEMMGR.LIB as this will be done implicitly for you
---------------------------------------------------------------------------
extern "C" __declspec(dllexport) __stdcall int myAdd(int,int);
extern "C" __declspec(dllexport) __stdcall AnsiString aboutMe(void);
int add(int n1,int n2);
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}
---------------------------------------------------------------------------
__declspec(dllexport) __stdcall int myAdd(int n1,int n2)
{
  int T;
  T=add(n1,n2);
  return T;
}
int add(int n1,int n2)
{
  return n1+n2;
}
__declspec(dllexport) __stdcall AnsiString aboutMe(void)
{
  return "曾棕根好你个大笨蛋,居然现在才学会用DLL!半年前施勇强就告诉了你呀!研究进度太慢!";

}
4、需要注意的是,在编写DLL这样的程序时,要力求简单,少用大量内存分配,尽量按照标准C的程序设计方法,以模块化结构设计为好,少采用面向对象的程序设计方法。
5、进入Project-Options:
      勾掉Linker页中的Use Dynamic RTL
      勾掉Packages页中的Build with runtime packages
      按一次Compiler中的Release按钮
      在Version Info页中勾选Include version information in project,并勾选Auto-increment build number,再在里面设置好版权信息
6、现在可以进入Project-Build myDLL生成myDLL.dll和myDLL.lib这两个文件。

二 静态调用动态链接库DLL
 

调用DLL有两种方式,一种是静态调用,另一种就是动态调用。静态调用需要LIB库文件和DLL文件,程序编译时,需要用到LIB文件,发布时这个LIB文件就不再需要,而且,编译系统时,这个动态链接库已编译进程序,这样,在程序一开始运行时就会查找这个DLL文件,如果这个DLL文件不存在,那么,程序是启动不起来的。相反,动态调用DLL则不是这样,它只需要DLL文件,程序运行时,程序不需要知道这个DLL文件当前是否存在,只有当程序运行到某个点,才需要去调用DLL文件多个应用程序调用DLL时,DLL 在内存中只产生一个实例,因此,可以有效地节省内存空间,提高系统的运行效率。注意到,DLL 的编制与编程语言无关,只要遵守DLL的接口规范,许多语言都可以开发出高效的DLL程序,其它语言开发的DLL,同样可以在BCB中调用。
下面介绍以myDLL.dll为例静态调用DLL的步骤:
1、将myDLL.dll和myDLL.lib文件拷入到开发工程中,注意到,应用程序发布时,这个lib文件是不需要的。如果是其它语言开发的DLL,在没有lib文件的情况下,可以用implib.exe工具程序,生成一个lib文件,用法:
implib.exe 文件名.lib 文件名.DLL
2、Project-Add to project将myDLL.lib库导入到工程。
如果要从工程中清除库文件,方法有两种:
a、Project-Remove from project
b、View-Project Manager
3、在工程的Unit1.cpp中写程序代码:
---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
extern "C" __declspec(dllimport) __stdcall int myAdd(int,int);
extern "C" __declspec(dllimport) __stdcall AnsiString aboutMe(void);
---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   int n;
   n=myAdd(1,2);
   ShowMessage(IntToStr(n));

}
---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  ShowMessage(aboutMe());        
}
---------------------------------------------------------------------------

三 动态调用动态链接库DLL 

动态调用DLL函数可分为八步:
第一步:函数定义。这里的函数为地址转换函数。下面这个函数其实就是定义 int __stdcall myAdd(int,int);
   int __stdcall (*myAdd)(int,int);
第二步:定义模块句柄,全局变量,它是载入DLL文件后的实例
   HINSTANCE HmyDLL;
第三步:装入DLL文件,同时获得它的句柄
  HmyDLL=LoadLibrary("myDLL.dll");
第四步:定义函数地址变量
   FARPROC  P;
第五步:获取动态链接库内的某一函数的内存地址
     P=GetProcAddress(HmyDLL,"myAdd");
第六步:强制类型转换,即将所获取的函数地址强制转换为函数
       myAdd=(int __stdcall (__cdecl *)(int,int))P;
第七步:函数调用
       n=myAdd(10,20);
第八步:释放DLL
  FreeLibrary(HmyDLL);

下面以动态调用myDLL.dll函数为例,进行讲解:
---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
第一步:函数定义。这里的函数为地址转换函数。下面这个函数其实就是定义 int __stdcall myAdd(int,int);
int __stdcall (*myAdd)(int,int);
AnsiString __stdcall (*aboutMe)(void);
第二步:定义模块句柄,全局变量,它是载入DLL文件后的实例
HINSTANCE HmyDLL;
---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  第三步:装入DLL文件,同时获得它的句柄
  HmyDLL=LoadLibrary("myDLL.dll");
}
---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   int n;
   第四步:定义函数地址变量
   FARPROC  P;
   if(HmyDLL!=NULL)
   {
     第五步:获取动态链接库内的某一函数的内存地址
     P=GetProcAddress(HmyDLL,"myAdd");
     if(P==NULL)
     {
       ShowMessage("打开myAdd()函数错误!");
     }
     else
     {
       第六步:强制类型转换,即将所获取的函数地址强制转换为函数
       myAdd=(int __stdcall (__cdecl *)(int,int))P;
       第七步:函数调用
       n=myAdd(10,20);
       ShowMessage(IntToStr(n));
     }
   }
   else
   {
     ShowMessage("打开动态链接库文件myDLL.dll错误!");
   }
}
---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
  第八步:释放DLL
  FreeLibrary(HmyDLL);
}
---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  FARPROC P;
  if(HmyDLL!=NULL)
  {
    P=GetProcAddress(HmyDLL,"aboutMe");
    if(P==NULL)
    {
      ShowMessage("打开aboutMe()函数错误!");
    }
    else
    {
      aboutMe=(AnsiString __stdcall (__cdecl *)(void))P;
      ShowMessage(aboutMe());
    }
   }
   else
   {
     ShowMessage("打开动态链接库文件myDLL.dll错误!");
   }
}
---------------------------------------------------------------------------
注意:动态调入myDLL.dll文件后,它在内存中只存在一个副本,这时,动态链接库文件已于关闭状态。


  • 1
    点赞
  • 1
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值