1、从建工程到实现注册
在这一过程中我们将完成三个步骤:创建dll的入口函数,定义接口文件,实现注册功能
1.1创建一个类型为win32 dll工程
创建一个名为MathCOM的win32 dll工程。
在向导的第二步选择"A smiple dll project"选项。当然如果你选择一个空的工程,那你自己完成DllMain定义吧。
1.2定义接口文件
生成一个名为MathCOM.idl的接口文件。并将此文件加入到刚才创建的那个工程里。
// MathCOM.idl : IDL source for MathCOM.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (MathCOM.tlb) and marshalling code.
import"oaidl.idl";
import"ocidl.idl";
[
uuid(FAEAE6B7-67BE-42a4-A318-3256781E945A),
helpstring("ISimpleMath Interface"),
object,
pointer_default(unique)
]
interfaceISimpleMath : IUnknown
{
HRESULTAdd([in]intnOp1,[in]intnOp2,[out,retval]int *pret);
HRESULTSubtract([in]intnOp1,[in]intnOp2,[out,retval]int *pret);
HRESULTMultiply([in]intnOp1,[in]intnOp2,[out,retval]int * pret);
HRESULTDivide([in]intnOp1,[in]intnOp2,[out,retval]int *pret);
};
[
uuid(01147C39-9DA0-4f7f-B525-D129745AAD1E),
helpstring("IAdvancedMath Interface"),
object,
pointer_default(unique)
]
interfaceIAdvancedMath : IUnknown
{
HRESULTFactorial([in]intnOp1,[out,retval]int *pret);
HRESULTFabonacci([in]intnOp1,[out,retval]int *pret);
};
[
uuid(CA3B37EA-E44A-49b8-9729-6E9222CAE844),
version(1.0),
helpstring("MATHCOM 1.0 Type Library")
]
libraryMATHCOMLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(3BCFE27E-C88D-453C-8C94-F5F7B97E7841),
helpstring("MATHCOM Class")
]
coclassMATHCOM
{
[default]interface ISimpleMath;
interfaceIAdvancedMath;
};
};
在编译此工程之前请检查Project/Setting/MIDL中的设置。正确设置如下图:
图1.4 midl的正确设置
在正确设置后,如编译无错误,那么将在工程的目录下产生四个
文件名 |
作用 |
MathCOM.h |
接口的头文件,如果想声明或定义接口时使用此文件 |
MathCOM_i.c |
定义了接口和类对象以及库,只有在要使用到有关与GUID有关的东西时才引入此文件,此文件在整个工程中只能引入一次,否则会有重复定义的错误 |
MathCOM_p.c |
用于存根与代理 |
dlldata.c |
不明 |
1.3增加注册功能
作为COM必须要注册与注销的功能。
1.3.1增加一个MathCOM.def文件
DEF文件是模块定义文件(Module Definition File)。它允许引出符号被化名为不同的引入符号。
; MathCOM.def : Declares the module parameters.
LIBRARY "MathCOM.DLL"
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllGetClassObject @2 PRIVATE
DllRegisterServer @3 PRIVATE
DllUnregisterServer @4 PRIVATE
DllUnregisterServer 这是函数名称 @4<――这是函数序号 PRIVATE
接下来大致介绍一下DllRegisterServer()和DllUnregisterServer()。(其他两个函数的作用将在后面介绍)
1.3.2 DllRegisterServer()和DllUnregisterServer()
DllRegisterServer() 函数的作用是将COM服务器注册到本机上。
DllUnregisterServer() 函数的作用是将COM服务器从本机注销。
1.4 MathCOM.cpp文件
现在请将 MathCOM.cpp 文件修改成如下:
// MATHCOM.cpp : Defines the entry point for the DLL application.
//
#include"stdafx.h"
#include<objbase.h>
#include<initguid.h>
#include"MathCOM.h"
#include"math.h"
#include"MathCOM_i.c"
//standard self-registration table
constchar * g_RegTable[][3]={
{ "CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}",0,"MathCOM"},
{ "CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\InprocServer32",0,(constchar * )-1 /*表示文件名的值*/},
{ "CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\ProgID",0,"tulip.MathCOM.1"},
{ "tulip.MathCOM.1",0,"MathCOM"},
{ "tulip.MathCOM.1\\CLSID",0,"{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}"},
};
HINSTANCE g_hinstDll;
BOOLAPIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOIDlpReserved
)
{
g_hinstDll=(HINSTANCE)hModule;
returnTRUE;
}
/*********************************************************************
* Function Declare : DllUnregisterServer
* Explain : self-unregistration routine
* Parameters :
* void --
* Return :
* STDAPI --
* Author : tulip
* Time : 2003-10-29 19:07:42
*********************************************************************/
STDAPIDllUnregisterServer(void)
{
HRESULThr=S_OK;
charszFileName [MAX_PATH];
::GetModuleFileName(g_hinstDll,szFileName,MAX_PATH);
intnEntries=sizeof(g_RegTable)/sizeof(*g_RegTable);
for(inti =0;SUCCEEDED(hr)&&i<nEntries;i++)
{
constchar * pszKeyName=g_RegTable[i][0];
longerr=::RegDeleteKey(HKEY_CLASSES_ROOT,pszKeyName);
if(err!=ERROR_SUCCESS)
hr=S_FALSE;
}
returnhr;
}
/*********************************************************************
* Function Declare : DllRegisterServer
* Explain : self Registration routine
* Parameters :
* void --
* Return :
* STDAPI --
* Author : tulip
* Time : 2003-10-29 19:43:51
*********************************************************************/
STDAPIDllRegisterServer(void)
{
HRESULThr=S_OK;
charszFileName [MAX_PATH];