3.实现plugins。
有了前两章的基础,这个就比较好办了。
先了解一点点基本概念:
Q:what is plugins
A:就是通过加载不同的dll实现不同的功能,或者附加的功能,典型的如模拟器的各种插件(显示,input...)。
Q:why we use plugins
A:主要为了使程序模块化,并且容易扩充。升级组件时不需要重新发布整个产品。
Q:how to do it?
A:使用LoadLibrary来加载具有相同接口(一般是函数,不过我们这里会使用C++类实现)的不同dll,实现/(扩充)功能。
例子:
D:/ePsxe/plugins>dumpbin spuseal.dll /exports
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file spuseal.dll
File Type: DLL
Section contains the following exports for spuSeal.dll
0 characteristics
36A22A22 time date stamp Sun Jan 17 10:21:22 1999
0.00 version
2 ordinal base
22 number of functions
22 number of names
ordinal hint RVA name
3 0 00001700 PSEgetLibName
2 1 00001710 PSEgetLibType
4 2 00001720 PSEgetLibVersion
6 3 00001800 SPUabout
11 4 00001EE0 SPUclose
5 5 00001730 SPUconfigure
18 6 00002090 SPUgetOne
7 7 00001910 SPUinit
10 8 00001B90 SPUopen
23 9 00002270 SPUplayADPCMchannel
12 A 00002250 SPUplaySample
17 B 00002050 SPUputOne
19 C 000020B0 SPUsetAddr
20 D 000020E0 SPUsetPitch
21 E 00002110 SPUsetVolumeL
22 F 00002150 SPUsetVolumeR
8 10 00001B80 SPUshutdown
13 11 00002190 SPUstartChannels1
14 12 000021C0 SPUstartChannels2
15 13 000021F0 SPUstopChannels1
16 14 00002220 SPUstopChannels2
9 15 00001880 SPUtest
Summary
1000 .rsrc
96000 UPX0
5000 UPX1
D:/ePsxe/plugins>
这个是epsxe的一个sound插件的输出表。可以看到epsxe就是通过这些函数与dll通信的。
进入正题:
从一个dll里面输出这么多函数实在是一个很烦的事情,而且一个个的去GetProcAddr也很麻烦,
能不能用简单一些的方法呢?
当然是可以的了,使用我们前面介绍的dll输出类技术2就可以了。
还是看代码,我们做一个input的plugins类。
;//input.h
class input{
virtual int Addref()=0;
virtual int Release()=0;
virtual DWORD QueryClsID()=0;//identify this is a input plugins;
virtual DWORD IsSupport(DWORD flags)=0;
virtual bool GetXY(int&x,int&y)=0;
virtual DWORD GetButtonStat()=0;
virtual bool AddEffect(DWORD id,DWORD level)=0;
virtual bool QueryInterface(DWORD clsid,LPVOID* ppVoid);//留待扩充。越来越像COM了。
virtual bool DoConfig();
protected:
input();
virtual ~input();
};
--------------------------------------------------------
;//mouseinput.h
class MouseInput
:public input
{
protected:
friend input* CreateInput(LPVOID pVoid);
;//...............
};
--------------------------------------------------------
;//mouseinput.cpp
input* CreateInput(LPVOID pVoid){return new mouseinput;};
--------------------------------------------------------
;//keyinput.h
class KeyInput
:public input
{
protected:
friend input* CreateInput(LPVOID pVoid);
;//...............
};
--------------------------------------------------------
;//keyinput.cpp
input* CreateInput(LPVOID pVoid){return new keyinput;};
编译后就得到了mouseinput.dll和keyinput.dll
他们分别输出mouseinput类和keyinput类,而外部程序是通过input的接口来调用他们,从而实现了plugins的功能。
不知道还有没有什么遗漏啊,请大家指教了......
多提意见:)
有了前两章的基础,这个就比较好办了。
先了解一点点基本概念:
Q:what is plugins
A:就是通过加载不同的dll实现不同的功能,或者附加的功能,典型的如模拟器的各种插件(显示,input...)。
Q:why we use plugins
A:主要为了使程序模块化,并且容易扩充。升级组件时不需要重新发布整个产品。
Q:how to do it?
A:使用LoadLibrary来加载具有相同接口(一般是函数,不过我们这里会使用C++类实现)的不同dll,实现/(扩充)功能。
例子:
D:/ePsxe/plugins>dumpbin spuseal.dll /exports
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file spuseal.dll
File Type: DLL
Section contains the following exports for spuSeal.dll
0 characteristics
36A22A22 time date stamp Sun Jan 17 10:21:22 1999
0.00 version
2 ordinal base
22 number of functions
22 number of names
ordinal hint RVA name
3 0 00001700 PSEgetLibName
2 1 00001710 PSEgetLibType
4 2 00001720 PSEgetLibVersion
6 3 00001800 SPUabout
11 4 00001EE0 SPUclose
5 5 00001730 SPUconfigure
18 6 00002090 SPUgetOne
7 7 00001910 SPUinit
10 8 00001B90 SPUopen
23 9 00002270 SPUplayADPCMchannel
12 A 00002250 SPUplaySample
17 B 00002050 SPUputOne
19 C 000020B0 SPUsetAddr
20 D 000020E0 SPUsetPitch
21 E 00002110 SPUsetVolumeL
22 F 00002150 SPUsetVolumeR
8 10 00001B80 SPUshutdown
13 11 00002190 SPUstartChannels1
14 12 000021C0 SPUstartChannels2
15 13 000021F0 SPUstopChannels1
16 14 00002220 SPUstopChannels2
9 15 00001880 SPUtest
Summary
1000 .rsrc
96000 UPX0
5000 UPX1
D:/ePsxe/plugins>
这个是epsxe的一个sound插件的输出表。可以看到epsxe就是通过这些函数与dll通信的。
进入正题:
从一个dll里面输出这么多函数实在是一个很烦的事情,而且一个个的去GetProcAddr也很麻烦,
能不能用简单一些的方法呢?
当然是可以的了,使用我们前面介绍的dll输出类技术2就可以了。
还是看代码,我们做一个input的plugins类。
;//input.h
class input{
virtual int Addref()=0;
virtual int Release()=0;
virtual DWORD QueryClsID()=0;//identify this is a input plugins;
virtual DWORD IsSupport(DWORD flags)=0;
virtual bool GetXY(int&x,int&y)=0;
virtual DWORD GetButtonStat()=0;
virtual bool AddEffect(DWORD id,DWORD level)=0;
virtual bool QueryInterface(DWORD clsid,LPVOID* ppVoid);//留待扩充。越来越像COM了。
virtual bool DoConfig();
protected:
input();
virtual ~input();
};
--------------------------------------------------------
;//mouseinput.h
class MouseInput
:public input
{
protected:
friend input* CreateInput(LPVOID pVoid);
;//...............
};
--------------------------------------------------------
;//mouseinput.cpp
input* CreateInput(LPVOID pVoid){return new mouseinput;};
--------------------------------------------------------
;//keyinput.h
class KeyInput
:public input
{
protected:
friend input* CreateInput(LPVOID pVoid);
;//...............
};
--------------------------------------------------------
;//keyinput.cpp
input* CreateInput(LPVOID pVoid){return new keyinput;};
编译后就得到了mouseinput.dll和keyinput.dll
他们分别输出mouseinput类和keyinput类,而外部程序是通过input的接口来调用他们,从而实现了plugins的功能。
不知道还有没有什么遗漏啊,请大家指教了......
多提意见:)