发信人: lofe ()感激生活(), 信区: BorlandDev
标  题: 动态链结函式库(Dynamic Linked Library)(6)
发信站: 哈工大紫丁香 (2000年08月30日19:53:01 星期三), 站内信件

新知识的实践

现在我们已了解DLL的使用,尚有另一种明确呼叫的方式,我们可以将前面的范例程式
修改为使用明确呼叫的方法来使用 DLL。

void (*ShowImage)(void);
void __fastcall TForm1::ShowButtonClick(TObject *Sender)
{
HINSTANCE hInst;
hInst = LoadLibrary("DLLSAMP.DLL");
(FARPROC &)ShowImage=GetProcAddress(hInst,"ShowImage");
ShowImage();
FreeLibrary(hInst);
}

以上就是修改後的程式,因为程式已改成明确呼叫的方式,因此不需要使用
DLLSAMP.LIB了,所以关於BCB和VC所使用的LIB档格式不同的问题也不存在了。在此我
简单地说明所使用的几个函式

hInst = LoadLibrary("DLLSAMP.DLL") 是用来载入DLLSAMP.DLL ,同时传回该DLL的
HINSTANCE值,它是据以使用DLL的权杖。
(FARPROC &)ShowImage=GetProcAddress(hInst,"ShowImage") 利用前面得到的
HINSTANCE值,呼叫GetProcAddress来得到ShowImage函式的位址,因为
GetProcAddress所传回的值为FARPROC ,因此我们必须做型别转换。在此我是利用
(FARPROC &) 以reference做型别转换。

FreeLibrary(hInst) 使用完後,利用FreeLibrary 将该DLL释放。

输入函式及输出函式的标准写法

前面我们使用输入函式及输出函式时,为了简化程式的写法,因此使用了Borland为了
和16位元程式相容而使用的 _export编译指令,在此我必须指出,这种写法是非标准
的写法,其实Microsoft在32位元程式中使用了另一种定义输入函式及输出函式的写
法,那才是一个放诸四海皆准的写法,使用 _export式的旧有写法在诸如Visual C++
的编译器中是无法通过编译的。

在理论上,我们希望可以使用单一的关键字来定义一个输出函式,就如同 _export一
般,然而Microsoft却在它的32位元程式中使用了另一种关键字来定义输入及输出函
式,那就是 __declspec关键字,它可以传入dllimport及dllexport两个参数,用来分
别代表输入函式及输出函式。

换句话说,若你要撰写输出函式,你必须使用 __declspec(dllexport) 来定义该函
式,反之若你要使用输入函式,则你必须使用 __declspec(dllimport) 来定义该函
式。

因此由於输入及输出函式的使用方式不同,你必须使用两个不同的include档来分别定
义之。若你不想如此麻烦,那麽就必须要使用巨集定义来达到一体多用的目的罗,这
对少数人持反对论点的人来说,简直是罪恶(还有人称之为巨集巫毒--macro
woodoo)。

Windows的实作名家Jeffrey Richter,也就是Advanced Windows的作者建议我们使用
以下的方法来达到一体多用的效果(同样是透过巨集巫毒)。

#ifndef _SHOWIMG_H_
#define _SHOWIMG_H_
#ifndef IMGDLL
#define EXTERN __declspec(dllimport)
#else
#define EXTERN __declspec(dllexport)
#endif
void EXTERN ShowImage(void);
#endif

如此一来,当你在撰写DLL时撰写可以撰写如下函式:

#define IMGDLL
#include "image.h"

当使用者在使用DLL时,则只要直接含入image.h即可。如此一来算是解决了利用
__declspec(dllimport) 和 __declspec(dllexport) 的不便了。

   * 必也正名乎的DLL函式命名
   * 谈完了标准写法,再来我们要谈谈一个更容易搞混的函式命名原则。本来在正常
     情况下,我们是不需要理会编译器的函式命名规则的,因为在使用同一样编译器
     的情况下,不会有什麽太大的问题。然而问题来了,由於DLL是动态连结函式
     库,因此它的目标就是希望可以让多个程式共享程式及资源。所以若是DLL只能
     为同一种编译器所使用,那麽它的用途就大打折扣了。因此我们还是必须了解函
     式的命名方法。同时由於函式命名方式在各种不同的编译器各不相同,因此我们
     也必须了解其相异处,最重要的是,我们必须找出其沟通的方式。

--
真正的程序员用C, 聪明的程序员用什么?——Inprise工具!

欢迎光临BorlandDev版,探讨Inprise编程

           独孤九剑的最高境界是不拿剑
           编程的最高境界是无所谓工具

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: malacs.hit.edu.cn]
※ 修改:·lofe 於 08月30日19:57:20 修改本文·[FROM: malacs.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.847毫秒