包括文章列表:
用VC++5.0 定 制 和 调 用 动 态 链 接 库

在 Visual C++ 中 建 立 MFC 扩 展 DLL 

DLL中的模板成员函数?

关于VC中的DLL的编程1

关于VC中的DLL的编程2

关于VC中的DLL的编程3

关于VC中的DLL的编程4

  

                  用VC++5.0 定 制 和 调 用 动 态 链 接 库 





山 东 省 泰 安 市

杨 波 

---- 



---- 动 态 链 接 库(dll) 是 包 含 共 享 函 数 库 的 二 进 制 文 件, 可 以 被 多 个 应 用 程 序

 同 时 使 用。 建 立 应 用 程 序 的 可 执 行 文 件 时, 不 必 将DLL 连 接 到 应 用 程 序 中, 而 

是 在 运 行 时 动 态 装 载DLL, 装 载 时DLL 被 映 射 到 调 用 进 程 的 地 址 空 间 中。 通 常 我

 们 在 调 用DLL 时 所 需 的DLL 文 件 必 须 位 于 以 下 三 个 目 录 之 一: 



---- (1)Windows 的 系 统 目 录:\windows\system; 



---- (2)DOS 中path 所 指 出 的 任 何 目 录; 



---- (3) 程 序 所 在 的 目 录; 



一. 动 态 链 接 库(DLL) 结 构

---- DLL 中 定 义 有 两 种 函 数: 导 出 函 数(export function) 和 内 部 函 数(internal function), 

导 出 函 数 可 以 被 其 他 模 块 调 用, 内 部 函 数 只 能 在DLL 内 部 使 用。 我 们 在 用C++ 定 

制DLL 文 件 时, 需 要 编 写 的 就 是 包 含 导 出 函 数 表 的 模 块 定 义 文 件(.DEF) 和 实 现 导 

出 函 数 功 能 的C++ 文 件。 下 面 以Sample.dll 为 例 介 绍DEF 文 件 和 实 现 文 件 的 结 构: 



---- 1. 模 块 定 义 文 件(.DEF) 是 由 一 个 或 者 多 个 用 于 描 述DLL 属 性 的 模 块 语 句 组 成

 的 文 本 文 件, 每 个.DEF 文 件 至 少 必 须 包 含 以 下 模 块 定 义 语 句: 



第 一 个 语 句 必 须 是LIBRARY 语 句, 指 出DLL 的 名 字。 



EXPORTS 语 句 列 出 被 导 出 函 数 的 名 字。 



可 以 使 用DESCRIPTION 语 句 描 述DLL 的 用 途( 此 句 可 选)。 



";" 对 一 行 进 行 注 释( 可 选) 

---- 2. 实 现 文 件(.cpp 文 件 为 例) 



---- 实 现 入 口 表 函 数 的.cpp 文 件 中, 包 含DLL 入 口 点 处 理 的API 函 数 和 导 出 函 数 的 代 码。 



二. 创 建Sample.dll 

---- 1. 首 先 创 建Sample.dll 的 工 程, 启 动VC++5.0 按 以 下 步 骤 生 成DLL 工 程: 



在 菜 单 中 选 择File\New\Project 



在 工 程 列 表 中 选 择Win32 Dynamic-Link Library 



在Project Name 中 输 入 工 程 名:Sample 



单 击Location 右 边 按 钮, 选 择c:\sample 目 录 



单 击OK 完 成, 至 此 已 创 建 了Sample.dll 的 工 程 文 件 

---- 2. 创 建Sample.def 文 件 



在 菜 单 中 选 择File\New\Text File 



输 入 以 下 完 代 码 后 保 存 文 件 名"Sample.def" 

;Sample.def 

     ;指出DLL的名字Sample,链接器将这个名 

字放到DLL导入库中

     LIBRARY Sample

     ;定义导出函数ShowMe()为例

     EXPORTS

       ShowMe

     ;def文件结束



---- 3. 创 建Sample.cpp 



.在菜单中选择File\New\C++ Source File项

     .输入以下代码后保存文件名"Sample.cpp"

     //Sample.cpp  

     #include 

     int ShowMe(void);

     //DllEntryPoint为DLL入口点函数, 

负责初试化并终止DLL

     BOOL WINAPI DllEntryPoint(HINSTANCE 

hDLL,DWORD dwReason,LPVOID Reserved)

     {

        switch(dwReason)

        {

        case DLL_PROCESS_ATTACH:

                {

                        break;

                }

        case DLL_PROCESS_DETACH:

                {

                        break;

                }

        }

        return TRUE;

     }

   int ShowMe(void)

   {

        //蜂鸣器响一下

        MessageBeep((WORD)-1);

        MessageBox("你好!");

        return 1;

   }



---- 4. 编 译DLL 文 件 ---- 从Build 菜 单 中 选 择Build Sample.DLL, 产 生Sample.DLL 文 件, 以 后 就 

可 以 随 时 调 用 了。 



三. 在 应 用 程 序 中 调 用DLL 文 件

---- 在 应 用 程 序 中 要 首 先 装 入DLL 后 才 能 调 用 导 出 表 中 的 函 数, 例 如 用MFC 创 建 基 

于 对 话 框 的 工 程Test, 并 在 对 话 框 上 放 置"Load" 按 钮, 你 就 必 须 添 加 装 载 代 码。

 ---- 1. 首 先 在TestDlg.cpp 的 首 部 添 加 变 量 设 置 代 码: 



//设置全局变量gLibSample用于存储DLL句柄

    HINSTANCE gLibSample=NULL;

//第二个变量ShowMe是指向DLL

库中ShowMe()函数的指针

    typedef int(* SHOWME)(void);

    SHOWME ShowMe;



    2.利用ClassWizard为"Load"按钮添加装载DLL的代码

    Void CTestDlg::OnLoadButton()

    {

     //要添加的代码如下

       if(gLibMyDLL!=NULL)

         {

          MessageBox("The Sample.DLL has already been load.");

          return;

         }

       //装载Sample.dll,未加路径,将在 

三个默认路径中寻找

       gLibSample=LoadLibrary("SAMPLE.DLL"); 

       //返回DLL中ShowMe()函数的地址

       ShowMe=(SHOWME)

GetProcAddress(gLibSample,"ShowMe");

    //代码添加完毕

    }



---- 3. 只 要DLL 装 载 成 功, 在 应 用 程 序 中 就 可 以 直 接 调 用ShowMe() 函 数, 此 时 已 完 成 了

 定 制 和 调 用DLL 的 全 部 过 程。 ---- 本 程 序 在Windows95,VC++5.0 中 运 行 通 过。 



在 Visual C++ 中 建 立 MFC 扩 展 DLL 


   我 们 编 写 了 一 个 扩 展 类 的 样 例 并 将 其 封 装 在 DLL 中 以 向 你 演 示 该 过 程。 

    有 经 验 的 Windows 编 程 人 员 都 逐 渐 放 弃 了 Windows SDK, 而 转 向 能 为 Windows 内 置 的 

低 级 机 制 提 供 高 级 抽 象 的 开 发 环 境。 这 种 转 移 的 一 个 主 要 受 益 者 是 Visual C++, 它 

依 靠 MFC 库 来 提 供 Windows API 的 面 向 对 象 的 视 图。 



    MFC 是 经 验 丰 富 的 编 程 人 员 掌 握 的 有 力 工 具, 但 它 离 完 美 还 相 距 甚 远。 事 实 

上, 我 所 认 识 的 以 MFC 编 程 为 谋 生 手 段 的 人 都 开 发 了 他 或 她 自 己 的 扩 展 集 合, 他 

们 以 MFC 类 作 为 基 础 类 来 派 生 自 己 的 类。 这 毕 竟 是 C++ 的 威 力。 如 果 某 个 类 不 能 满 

足 你 的 需 求 ( 而 且 如 果 它 恰 好 可 以 作 为 设 计 的 开 始 ), 你 可 以 从 它 自 由 地 派 生 新 

类 并 修 改 你 不 喜 欢 的 部 分。 



    假 设 你 编 写 了 一 个 MFC 扩 展 集 合, 并 愿 意 与 公 司 的 其 它 开 发 人 员 共 享。 你 该 

如 何 封 装 这 些 扩 展 呢? 你 可 以 分 发 源 代 码 文 件 或 与 Visual C++ 组 件 库(Component Gallery) 兼 

容 的 组 件。 或 许 你 可 以 象 MFC 那 样 在 DLL 中 封 装 你 的 扩 展。 就 象 传 统 的 DLL 能 够 导 出 

函 数 一 样, MFC 扩 展 DLL 可 以 导 出 类。 任 何 动 态 链 接 到 MFC DLL 的 应 用 程 序 都 能 动 态 链 

接 到 MFC 扩 展 DLL。 作 为 开 发 者, 你 只 需 使 其 包 括 必 要 的 头 文 件 并 在 应 用 程 序 的 链 接

 列 表 中 添 加 DLL 导 入 库。 



   编 写 MFC 扩 展 DLL 困 难 吗? 有 了 Visual C++ 和 MFC 的 支 持, 这 实 际 非 常 轻 松。 本 文 解 释

 了 如 何 创 建 MFC 扩 展 DLL 来 弥 补 MFC 的 CToolTipCtrl 类 的 明 显 不 足。 一 旦 意 识 到 其 简 便 

性, 你 会 忍 不 住 亲 自 编 写 几 个 MFC 的 扩 展。 



    编 写 MFC 扩 展 DLL 



   从 理 论 角 度 而 言, MFC 的 CTool-TipCtrl 类 简 化 了 将 提 示 信 息(ToolTip) 与 对 话 框 的 控 件 

或 窗 口 的 任 意 区 域 相 关 联 的 过 程。 ( 提 示 信 息 是 当 鼠 标 光 标 停 滞 于 工 具 栏 按 钮 或 其 

它 UI 对 象 时 弹 出 的 小 型 帮 助 文 本 窗 口。 ) 但 有 个 问 题 尚 待 解 决。 由 于 CToolTipCtrl::AddTool 

不 能 自 动 成 为 提 示 信 息 依 附 的 窗 口 的 子 类, 因 此 鼠 标 事 件 必 须 手 工 转 交 给 提 示 信 息 

控 制。 这 通 常 意 味 着 你 必 须 自 己 给 窗 口 建 立 子 类。 



    如 果 你 给 CToolTipCtrl 对 象 下 的 提 示 信 息 控 制 传 送 了 正 确 的 标 志, 它 应 该 能 给 自 己 

创 建 子 类 -- 这 显 然 是 被 MFC 设 计 组 忽 略 的 功 能。 幸 运 的 是, 该 疏 忽 并 不 难 以 纠 正。 只 

要 从 CToolTipCtrl 类 中 派 生 出 一 个 类, 用 类 似 的 函 数 代 替 CToolTipCtrl::AddTool 即 可, 该 函 

数 的 TTM_ADDTOOL 消 息 使 用 TOOLINFO 结 构, 它 的 uFlags 域 中 包 含 TTF_SUBCLASS 标 志。 更 好 的 方 

式 是 用 两 个 函 数 代 替 它: 它 们 分 别 给 子 窗 口 和 矩 形 窗 口 区 域 添 加 提 示 信 息。 AddTool 

函 数 同 时 支 持 两 者, 但 在 语 法 结 构 上 创 建 提 示 信 息 的 两 种 方 法 截 然 不 同。 



    图 1 和 图 2 显 示 了 名 为 CToolTip-CtrlEx 的 CToolTipCtrl 的 派 生 类 的 源 代 码。 该 派 生 类 给 

它 继 承 的 内 容 添 加 了 两 个 函 数, 其 一 CToolTipCtrl::AddWindow 将 提 示 信 息 与 子 窗 口 相 关 联, 

其 二 AddRectangle 使 提 示 信 息 依 附 于 窗 口 的 矩 形 区 域。 这 两 个 函 数 都 使 用 了 TTF_SUBCLASS 标 

志 以 使 提 示 信 息 的 创 建 过 程 尽 可 能 简 单。 假 设 m_tooltipCtrl 是 CToolTipCtrlEx 对 象, 给 控 制 

ID 为 IDC_BUTTON 的 按 钮 添 加 提 示 信 息 就 非 常 容 易 了: 



    m_tooltipCtrl.AddWindow ( 



    GetDlgItem (IDC_BUTTON), 



    "Enter tooltip text here!"); 



    如 何 将 CToolTipCtrlEx 类 封 装 至 DLL 呢? 以 下 是 在 Visual C++ 4.x 中 的 详 细 步 骤: 



    1. 启 动 Visual C++ 并 通 过 从 File 菜 单 选 择 New 来 创 建 新 项 目, 双 击 Project Workspace。 

在 New Project Workspace 的 Name 框 中 输 入 "MfcExt"( 不 带 引 号 )。 在 Type 框 中 选 择 MFC AppWizard(dll)。 

然 后 点 击 Create 按 钮。 



    2. 在 AppWizard 的 Step 1 对 话 框 中, 通 过 在"What type of DLL would you like to create?" 项 中 选 

择"MFC Extension DLL(using shared MFC DLL)"。 点 击 Finish 按 钮, 然 后 点 击 OK 产 生 DLL 的 初 始 代 码。

 注 意"MFC Extension DLL" 后 括 弧 中 显 示 的"using shared MFC DLL"。 当 你 编 写 MFC 扩 展 DLL 时, 不 能 

选 择 静 态 链 接 至 MFC。 DLL 必 须 动 态 链 接 到 MFC 库。 



    3. 弹 出 ClassWizard 并 点 击 Add Class 按 钮。 选 择 New 打 开 Create New Class 对 话 框。 在 其 中 

标 有"Base class" 的 框 中 选 择 CToolTipCtrl, 在 标 有"Name" 的 框 中 输 入"CToolTipCtrlEx"。 使 用 Change 

按 钮 将 文 件 名 改 为 Tooltip.h 和 Tooltip.cpp。(改 变 文 件 名 并 不 是 绝 对 必 要 的, 我 这 样 做 是 

为 了 避 免 长 文 件 名。) 不 要 选 中"Add to Component Gallery" 框 以 节 省 磁 盘 空 间。 点 击 Create 命 

令 ClassWizard 执 行 类 派 生, 而 后 点 击 OK 退 出 ClassWizard。 



    4. 如 图 2 所 示, 给 CToolTipCtrlEx 类 添 加 成 员 函 数 AddWindow 和 AddRectangle。 由 于 这 两 个 函 

数 要 在 CToolTipCtrlEx 外 被 访 问, 因 此 确 定 它 们 都 是 public 的。 技 巧: 在 Visual C++ 中 给 类 添 加 

成 员 函 数 的 简 便 方 法 是 在 ClassView 窗 口 中 右 击 类 名, 并 从 快 捷 菜 单 中 选 择 Add Function。 



    5. 在 ClassView 窗 口 中, 双 击 CToolTipCtrlEx 打 开 类 的 头 文 件。 在 类 说 明 的 class 关 键 字 后 

添 加 AFX_EXT_CLASS(参 见 图 1)。 



    6. 建 立 项 目。 你 将 产 生 两 个 重 要 文 件: DLL 本 身(Mfcext.dll) 以 及 DLL 的 导 入 库(Mfcext.lib)。 

导 入 库 基 本 上 是 导 出 函 数 名 的 列 表 -- 或 者, 在 本 例 中 是 一 系 列 导 出 类。 链 接 至 导 入 库 使 

应 用 程 序 能 使 用 从 MFC 扩 展 DLL 中 导 出 的 类, 就 如 同 包 含 类 的 库 是 静 态 链 接 的 一 样。 与 

Mfcext.lib 链 接 还 使 得 Windows 知 道 应 用 程 序 需 要 Mfcext.dll 才 能 运 行。 



    使 用 MFC 扩 展 DLL 



  创 建 使 用 Mfcext.dll 的 应 用 程 序 是 轻 而 易 举 的。 只 要 确 保 在 使 用 CToolTipCtrlEx 的 每 个 类 中 

包 括 Tooltip.h 头 文 件, 并 且 将 Mfcext.lib 添 加 至 项 目 的 链 接 库 列 表 中 即 可。 然 后 CToolTipCtrlEx 

就 可 以 象 普 通 MFC 类 那 样 使 用 了。 当 回 答 AppWizard 的 询 问 时 一 定 要 选 择"As a shared DLL", 这 样 

你 的 应 用 程 序 才 能 动 态 链 接 至 MFC。 你 可 以 通 过 从 Visual C++ 的 Build 菜 单 中 选 择 Settings 将 

Mfcext.lib 添 加 至 项 目 的 链 接 列 表 中, 点 击 Link 标 签 并 在 标 有"Object/library modules" 的 框 中 输 

入 Mfcext.lib 的 路 径(参 见 图 3)。 



    ToolTest 是 作 为 样 例 的 应 用 程 序, 它 在 对 话 框 中 显 示 一 个 按 钮。 它 动 态 链 接 至 Mfcext.dll 

并 使 用 CToolTipCtrlEx。 该 应 用 程 序 是 基 于 对 话 框 的, dialog 类 包 含 名 为 m_tooltipCtrl 的 CToolTipCtrlEx 

成 员 变 量。 对 话 框 的 OnInitDialog 函 数 中 的 以 下 代 码 创 建 提 示 信 息 控 制 并 给 对 话 框 的 按 钮 设 置

 提 示 信 息: 



    m_tooltipCtrl.Creat (this); 



    m_tooltipCtrl.AddWindowTool ( 



    GetDlgItem (IDC_EXIT), 



    "Click here to close"); 



    当 光 标 停 在 按 钮 上 时, 提 示 信 息 窗 口 中 显 示"Click here to close"。 点 击 该 按 钮 可 以 关 闭 

应 用 程 序。 



    你 可 以 从 PC Magazine Online(www.pcmag.com) 下 载 ToolTest 和 Mfcext.dll 的 完 整 源 代 码。 从 主 页 

左 侧 的 菜 单 中 选 择 Downloads, 然 后 依 次 选 择 PC Tech Archives 和 文 件 V16n15.zip。 CompuServe 的 

Utilities/Tips 论 坛(GO ZNT:TIPS) 上 也 有 该 文 件。 我 们 的 文 件 包 含 在 该 归 档 文 件 中。 使 用 PKUNZIP 

的 -d 开 关 解 压 文 件(Mfcext.zip 和 Tooltest.zip), 以 便 .ZIP 文 件 中 的 目 录 也 能 一 同 被 解 压。 在 运

 行 ToolTest 之 前, 将 Mfcext.dll 拷 贝 至 Windows 系 统 目 录 或 Tooltest.exe 所 在 的 目 录。 否 则, 当 执 行

 ToolTest 时, Windows 可 能 找 不 到 Mfcext.dll。 如 果 你 打 算 建 立 自 己 的 Tooltest.exe 版 本, 修 改 Project 

Settings 对 话 框 的"Object/library modules" 框 的 路 径 名, 使 Visual C++ 能 获 悉 在 PC 的 何 处 寻 找 Mfcext.lib 

文 件。 



    总 结 



    创 建 MFC 扩 展 DLL 非 常 容 易 -- 只 要 你 知 道 了 该 如 何 操 作。 当 你 给 其 它 开 发 人 员 分 发 MFC

 扩 展 DLL 时, 不 要 忘 记 提 供 描 述 DLL 中 类 的 头 文 件 以 及 相 应 的 .LIB 文 件 和 DLL 本 身。 此 后 开 

发 人 员 就 能 充 分 利 用 你 装 配 的 扩 展 了。 

 







DLL中的模板成员函数?

 







在一个DLL中,我在自己创建的类中使用了模板成员函数来代替预处理宏.但出现以下错误:



  error C2664: 'double Data::extract(double &)' : cannot convert parameter 1

  from 'class CArray' to 'double &'

为什么在匹配模板定义时它要寻找一个DOUBLE参数?



我觉得你可能是在表达成员函数(内联)时出现了问题,请参照下面的示例:

   class AFX_EXT_CLASS Data : public CObject //This is not a template

   {

   public:

      Data();

      Data(BYTE * buffer,int size);

      template

      Data(const CArray& array);

      template

      CArray& extract(CArray& array)

      {

         CArchive ar(&buffer, CArchive::store);

         ar >> array;

      };

      double extract(double&);

                 (...)

   private:

      CMemFile buffer;

   }



关于VC中的DLL的编程

 



在我们实际用软件时,经常可看到许多动态连接库。动态连接库有其自身的优点

如节省内存、支持多语种等功能,而且,当DLL中的函数改变后,只要不是参数的改变

调用起的函数并不需要重新编译。这在编程时十分有用。至于其他妙处,各位在电脑

杂志、书籍中都能看到,我这里再说就是废话了.

这次小弟我所要讲的是如何在VC5.0中如何做自己的Win32 DLLs,各位要做自己的

动态连接库,首先要知道DLL在VC5.0中都有哪几种分类。VC支持三种DLL,它们是:



1.Non-MFC Dlls

2.Regular Dlls

3.Extension Dlls Note:翻译措辞不当,故遇到术语是引用原词



Non-MFC DLL:指的是不用MFC的类库结构,直接用C语言写的DLL,其输出的函数一

般用的是标准C接口,并能被非MFC或MFC编写的应用程序所调用。LL,

Regular DLL:和下述的Extension Dlls一样,是用MFC类库编写的。明显的特点是

在源文件里有一个继承CWinApp的类。其又可细分成静态连接到MFC和动态连接到MFC上

的。但静态连接到MFC的动态连接库只被VC的专业般和企业版所支持。

Extension DLL:用来实现从MFC所继承下来的类的重新利用,也就是说,用这种类

型的动态连接库,可以用来输出一个从MFC所继承下来的类。Extension DLL使用MFC的

动态连接版本所创建的,并且它只被用MFC类库所编写的应用程序所调用。

各位看到这里如果眼有点花或头有点晕,请别泄气,再看两遍,然后继续往下看,

定有收获。



标 题: 关于VC中的DLL的编程[1]



这一节介绍Non-MFC DLLs的编写方法。下面是一个通用的

写法:



BOOL APIENTRY DllMain(HANDLE 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:

.......

}

return TRUE;

}

每一个DLL必须有一个入口点,这就象我们用C编写的应用程序一样,

必须有一个WINMAIN函数一样。

在这个示例中,DllMain是一个缺省的入口函数,你不需要编写自己

的DLL入口函数,并用linker的命令行的参数开关/ENTRY声明。用这个缺

省的入口函数就能使动态连接库被调用时得到正确的初始化,当然了,你

不要在初始化的时候填写使系统崩溃的代码了。

参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄

(实际上,它是指向_DGROUP段的一个选择符)

ul_reason_for_call是一个说明动态库被调原因的标志。当进程或线程

装入或卸载动态连接库的时候,操作系统调用入口函数,并说明动态连接库

被调用的原因。它所有的可能值为:

DLL_PROCESS_ATTACH: 进程被调用

DLL_THREAD_ATTACH: 线程被调用

DLL_PROCESS_DETACH: 进程被停止

DLL_THREAD_DETACH: 线程被停止

lpReserved是一个被系统所保留的参数。

入口函数已经写了,盛下的也不难,你可以在文件中加入你所想要输

出的函数或变量或c++类或、或、或、?好象差部多了。Look here!现在就

要加入一个新的输出函数了:

void _declspec(dllexport) JustSoSo()

{

MessageBox(NULL,"It's so easy!","Hahaha......",MB_OK);

}

要输出一个类也可以,如下:

class _declspec(dllexport) Easy

{

//add your class definition...

};

各位一定注意到在输出函数或类是我用到_declspec(dllexport),

这是VC提供的一个关键字,用它可在动态连接库中输出一个数据、

一个函数或一个类。用这个关键字可省你不少事,你不用在.DEF文件

中说明我要输出这个类、那个函数的。

Ok!各位照着上面的例子试着敲敲看,Just so easy!

先说到这了



发信人: dragon (龙), 信区: VC

标 题: 关于VC中的DLL的编程[2]



前面讲到Non-MFC DLL的编法,现在讲讲调用DLL的方法。对DLL的

调用分为两种,一种是显式的调用,一种是隐式的调用。

所谓显式的调用,是指在应用程序中用LoadLibrary或MFC提供的

AfxLoadLibrary显式的将自己所做的动态连接库调近来,动态连接库

的文件名即是上两函数的参数,再用GetProcAddress()获取想要引入

的函数。自此,你就可以象使用如同本应用程序自定义的函数一样来

调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或

MFC提供的AfxLoadLibrary释放动态连接库。





隐式的调用则需要把产生动态连接库时产生的.LIB文件加入到应

用程序的工程中,想使用DLL中的函数时,只须说明以下,如下:说明

上篇的输出函数void JustSoSo();

隐式调用不需要调用LoadLibrary()和FreeLibrary().



由此看来,隐式说明调用的方法比较简单,但DLL改变后,应用程序

须从新编译。并且,所有所调用的DLL在应用程序加载的同时被加载到内

存中,但应用程序调用的DLL比较多时,装入的过程十分慢。隐式的调用

则在应用程序不知道所要装入的DLL或隐式调用不成功,此时,允许用户

指定所要加载的动态连接库,比较灵活



发信人: dragon (龙), 信区: VC

标 题: 关于VC中的DLL的编程[3]



Regular DLL能够被所有支持DLL技术的语言所编写的应用程序

所调用。在这种动态连接库中,它必须有一个从CWinApp继承下来的

类,DllMain函数被MFC所提供,不用自己显式的写出来。下面是一个

例子:

// MyRegularDll.h:main header file for the MYREGULARDLL DLL

#include "resource.h" // main symbols



class CMyRegularDllApp : public CWinApp

{

public:

CMyRegularDllApp();

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CMyRegularDllApp)

//}}AFX_VIRTUAL



//{{AFX_MSG(CMyRegularDllApp)

// NOTE - the ClassWizard will add and

// remove member functions here.

// DO NOT EDIT what you see in these blocks

// of generated code !

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};



//MyRegularDll.cpp:Defines the initialization routines for the DLL.

//



#include "stdafx.h"

#include "MyRegularDll.h"

// Note!

//

// If this DLL is dynamically linked against the MFC

// DLLs, any functions exported from this DLL which

// call into MFC must have the AFX_MANAGE_STATE macro

// added at the very beginning of the function.

//

// For example:

//

// extern "C" BOOL PASCAL EXPORT ExportedFunction()

// {

// AFX_MANAGE_STATE(AfxGetStaticModuleState());

// // normal function body here

// }

//

// It is very important that this macro appear in each

// function, prior to any calls into MFC. This means that

// it must appear as the first statement within the

// function, even before any object variable declarations

// as their constructors may generate calls into the MFC

// DLL.



BEGIN_MESSAGE_MAP(CMyRegularDllApp, CWinApp)

//{{AFX_MSG_MAP(CMyRegularDllApp)

// NOTE - the ClassWizard will add

// and remove mapping macros here.

// DO NOT EDIT what you see in these blocks

END_MESSAGE_MAP()

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

// CMyRegularDllApp construction

CMyRegularDllApp::CMyRegularDllApp()

{

// TODO: add construction code here,

// Place all significant initialization in InitInstance

}

以上是AppWizard产生的含有主要代码的两个文件,各位可从中

看出和Non-MFC Dlls的区别。但要注意上面的AppWizard的提醒啊。



 



发信人: dragon (龙), 信区: VC

标 题: 关于VC中的DLL的编程[4]

发信站: 饮水思源站 (Thu Mar 25 00:46:22 1999) , 站内信件



这次要讲的是最后一种动态连接库:Extension Dlls.再次说明,

Extension Dll只被用MFC类库所编写的应用程序所调用.在这种动态

连接库中,你可以从MFC继承你所想要的、更适于你自己用的类,并

把它提供给你的应用程序。你也可随意的给你的应用程序提供MFC或

MFC继承类的对象指针。

Extension DLLs 和Regular DLLs不一样,它没有一个从CWinApp

继承而来的类的对象,所以,你必须为自己DllMain函数添加初始化

代码和结束代码.如下:



#include "stdafx.h"

#include 



static AFX_EXTENSION_MODULE PROJNAMEDLL = { NULL, NULL };



extern "C" int APIENTRY

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

{

if (dwReason == DLL_PROCESS_ATTACH)

{

TRACE0("PROJNAME.DLL Initializing!\n");



// Extension DLL one-time initialization

AfxInitExtensionModule(PROJNAMEDLL,

hInstance);



// Insert this DLL into the resource chain

new CDynLinkLibrary(Dll3DLL);

}

else if (dwReason == DLL_PROCESS_DETACH)

{

TRACE0("PROJNAME.DLL Terminating!\n");

}

return 1; // ok

}

在上面代码中AfxInitExtensionMoudle函数捕捉此动态库模块

用.

在初始化的时NEW一个CDynLinkLibrary对象的目的在于:它

能是Extension DLL想应用程序输出CRuntimeClass对象或资源.

如果此动态连接库被显式的调用,还必须在DLL_PROCESS_DETACH

选择项的执行代码上调用AfxTermEXtensonModule,这保证了当调

用进程与动态连接库分离是正确清理内存中的动态库模块。如果是

隐式的被调用,则此步不是必须的了。