DLL编写与调用

一 编写动态链接库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文件后,它在内存中只存在一个副本,这时,动态链接库文件已于关闭状态。

时间: 2024-11-08 20:55:27

DLL编写与调用的相关文章

VB.NET中的DLL编写和调用的最简单示例

DLL(动态链接库)是一个很有用的东西,在开发大项目的时候显得非常重要,因为多人合作开发时,可以给每个人分配一个任务,用DLL完成,最后组合起来,就不会出现互相冲突的问题.这里给出最简单的DLL编写与调用的示例,本人水平不高,各位看官莫笑. 首先,我们打开VB.NET,选择类库,名称改为test然后我们输入以下代码 Public Class test Public Function test(ByVal a As Long, ByVal b As Long) As Long Return a +

DLL编写与调用全解

DELPHI学习   2008-12-23 22:52   阅读8   评论0 字号: 大  中  小 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会陌生,在Windows中有着大量的以DLL为后缀的文件,它们是保证Windows正常运行和维护升级的重要保证.(举个例子,笔者的Win95 System目录下尽有500多个DLL文件.)其实,DLL是一种特殊的可执行文件.说它特殊主要是因为一般它都不能直接运行,需要宿主程序比如*.EXE程序或其他DLL的动态调用才能够使用.

delphi编写与调用DLL(delphi7下测试通过)

http://blog.sina.com.cn/s/blog_4dbbf76f01000anz.html 1 delphi编写DLL 2 下面在delphi中编写一个简单的dll,在该dll中只有一个max函数,返回2个数中的大数(Delphi 5.0) 3 1.New->DLL;取名为DLL_0001,编写代码: 4 library dll_0001; 5 uses 6 SysUtils, 7 Classes; 8 {$R *.RES} 9 function max(x,y:integer):

delphi 基础之三 编写和调用dll文件

delphi 编写和调用dll文件   Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs).一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数. 在如下几种情况下,调用DLL 是合理的: 1) 不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销. 2) 当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动. 3) 由于DLL 是独立于语言的,所以,当不同语言习惯的人共同开

delphi编写与调用DLL

delphi编写DLL 下面在delphi中编写一个简单的dll,在该dll中只有一个max函数,返回2个数中的大数(Delphi 5.0) 1.New->DLL;取名为DLL_0001,编写代码: library dll_0001; uses  SysUtils,  Classes; {$R *.RES} function max(x,y:integer):integer;stdcall;begin    if(x>y) then     max :=x     else     max :

Delphi 中的DLL 封装和调用对象技术(刘艺,有截图)

Delphi 中的DLL 封装和调用对象技术本文刊登2003 年10 月份出版的Dr.Dobb's 软件研发第3 期刘 艺摘 要DLL 是一种应用最为广泛的动态链接技术但是由于在DLL 中封装和调用对象受到对象动态绑定机制的限制使得DLL 在封装对象方面有一定的技术难度导致有些Delphi 程序员误以为DLL 只支持封装函数不支持封装对象本文着重介绍了DLL 中封装和调用对象的原理和思路并结合实例给出了多种不同的实现方法关键字动态链接库DLL 对象接口虚方法动态绑定类引用面向对象1 物理封装与动

C#写的dll跨语言调用

C#写的dll为非标准的windows下dll,故 一般其他语言不能直接调用,当然基于.net平台下的编程语言是可以调用,要让其他语言调用C#写的dll一般通过webservice服务或者是Com 方式.经过在网上找资料以及自身的实践发现可以通过以下方式在Delphi和VB语言中调用. 1.编写C#写dll,用VS新建一个类库项目TestDll,源码如下: using System; using System.Collections.Generic;using System.Text;using

DLL 编写与使用

DLL 编写与使用 DLL,Dynamic Link Library,动态链接库.这是微软的一项技术,必须包含<windows.h>. vs2010创建dll项目 流程: File|New|Project|Visual C++|Win32 | Win32 Console Application|DLL(Additional options|Export symbols) 以工程名12345为例. 项目生成,就会有 12345.dll 12345.lib两个文件. 头文件是声明 lib是函数入口

Visual Studio 2010生成dll文件并调用(C#)

1.创建新C#控制台应用程序,项目命名createBll,打开Program.cs重命名为TestA(可以不重命名)并修改代码,如图: 写好后,可以写其它的类.cs文件 2.完成后,点击菜单栏的"项目",下拉单选择"createDll属性",打开如图窗口 在输出类型选择"类库",然后关掉该窗口,生成解决方案,即生成了creatBll.dll文件,在项目下createBll\createBll\bin\Debug\createBll.dll目录下.