在Windows平台上编写dll的时候.一个dll应该要包括下面的方法。
1.DllMain方法
DllMain方法和可执行程序的WinMain类似,是dll的入口函数。在dll装载和卸载等时候,都会被调用。这样dll的作者就有机会处理初始化和清理资源。下面是一个DllMain的样例代码:
2.在引用dll的时候必须要将dll拷贝到可执行程序所在的目录下面。为了让其他地方的代码也可以调用该dll。就必须在操作系统中注册这个dll.和注册有关的方法有两个。下面是样例代码:
注册用到了CDllRegistrar类,这是一个Helper类。代码如下:
#if !defined(_REGISTRAR_H)
#define _REGISTRAR_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include " stdio.h "
class CRegistrar
{
protected:
CRegistrar() {};
BOOL SetInRegistry(HKEY hRootKey, LPCSTR subKey, LPCSTR keyName,LPCSTR keyValue)
{
HKEY hKeyResult;
DWORD dataLength;
DWORD dwDisposition;
if (RegCreateKeyEx( hRootKey, subKey, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hKeyResult, &dwDisposition) != ERROR_SUCCESS)
{
return FALSE;
}
dataLength = strlen(keyValue);
DWORD retVal = RegSetValueEx( hKeyResult, keyName, 0, REG_SZ,(const BYTE *) keyValue, dataLength);
RegCloseKey(hKeyResult);
return (retVal == ERROR_SUCCESS) ? TRUE:FALSE;
}
BOOL DelFromRegistry(HKEY hRootKey, LPCTSTR subKey)
{
long retCode;
retCode = RegDeleteKey(hRootKey, subKey);
if (retCode != ERROR_SUCCESS)
return false;
return true;
}
bool StrFromCLSID(REFIID riid,LPSTR strCLSID)
{
LPOLESTR pOleStr = NULL;
HRESULT hr = ::StringFromCLSID(riid,&pOleStr);
if(FAILED(hr))
return false;
int bytesConv = ::WideCharToMultiByte(CP_ACP,0,pOleStr,wcslen(pOleStr),strCLSID,MAX_PATH,NULL,NULL);
CoTaskMemFree(pOleStr);
strCLSID [ bytesConv ] = '';
if(!bytesConv)
{
return false;
}
return true;
}
public:
bool RegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!strlen(ClassId))
return false;
if(!StrFromCLSID(riid,strCLSID))
return false;
if(!strlen(LibId) && strlen(ClassId))
sprintf(Buffer,"%s.%s/CLSID",ClassId,ClassId);
else
sprintf(Buffer,"%s.%s/CLSID",LibId,ClassId);
BOOL result;
result = SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",strCLSID);
if(!result)
return false;
sprintf(Buffer,"CLSID/%s",strCLSID);
char Class [ MAX_PATH ];
sprintf(Class,"%s Class",ClassId);
if(!SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Class))
return false;
sprintf(Class,"%s.%s",LibId,ClassId);
strcat(Buffer,"/ProgId");
return SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Class) ? true:false;
}
bool UnRegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"%s.%s/CLSID",LibId,ClassId);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"%s.%s",LibId,ClassId);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"CLSID/%s/ProgId",strCLSID);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"CLSID/%s",strCLSID);
return DelFromRegistry(HKEY_CLASSES_ROOT,Buffer) ? true:false;
}
} ;
class CDllRegistrar : public CRegistrar
{
public:
bool RegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId,LPCSTR Path)
{
if(! CRegistrar::RegisterObject(riid,LibId,ClassId))
return false;
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"CLSID/%s/InProcServer32",strCLSID);
return SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Path) ? true:false;
}
bool UnRegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"CLSID/%s/InProcServer32",strCLSID);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
return CRegistrar::UnRegisterObject(riid,LibId,ClassId);
}
} ;
#endif
1.DllMain方法
DllMain方法和可执行程序的WinMain类似,是dll的入口函数。在dll装载和卸载等时候,都会被调用。这样dll的作者就有机会处理初始化和清理资源。下面是一个DllMain的样例代码:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_module = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_module = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
STDAPI DllRegisterServer(
void
)
{
// 这个类应该创建标准的注册表入口
CDllRegistrar registrar;
char path [ MAX_PATH ];
GetModuleFileName((HMODULE)g_module,path,MAX_PATH);
return registrar.RegisterObject(CLSID_Mine,"MineLib","MathObj",path) ? S_OK:S_FALSE;
}
STDAPI DllUnregisterServer( void )
{
CDllRegistrar registrar;
return registrar.UnRegisterObject(CLSID_Mine,"MineLib","MathObj") ? S_OK:S_FALSE;
}
{
// 这个类应该创建标准的注册表入口
CDllRegistrar registrar;
char path [ MAX_PATH ];
GetModuleFileName((HMODULE)g_module,path,MAX_PATH);
return registrar.RegisterObject(CLSID_Mine,"MineLib","MathObj",path) ? S_OK:S_FALSE;
}
STDAPI DllUnregisterServer( void )
{
CDllRegistrar registrar;
return registrar.UnRegisterObject(CLSID_Mine,"MineLib","MathObj") ? S_OK:S_FALSE;
}
#if !defined(_REGISTRAR_H)
#define _REGISTRAR_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include " stdio.h "
class CRegistrar
{
protected:
CRegistrar() {};
BOOL SetInRegistry(HKEY hRootKey, LPCSTR subKey, LPCSTR keyName,LPCSTR keyValue)
{
HKEY hKeyResult;
DWORD dataLength;
DWORD dwDisposition;
if (RegCreateKeyEx( hRootKey, subKey, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hKeyResult, &dwDisposition) != ERROR_SUCCESS)
{
return FALSE;
}
dataLength = strlen(keyValue);
DWORD retVal = RegSetValueEx( hKeyResult, keyName, 0, REG_SZ,(const BYTE *) keyValue, dataLength);
RegCloseKey(hKeyResult);
return (retVal == ERROR_SUCCESS) ? TRUE:FALSE;
}
BOOL DelFromRegistry(HKEY hRootKey, LPCTSTR subKey)
{
long retCode;
retCode = RegDeleteKey(hRootKey, subKey);
if (retCode != ERROR_SUCCESS)
return false;
return true;
}
bool StrFromCLSID(REFIID riid,LPSTR strCLSID)
{
LPOLESTR pOleStr = NULL;
HRESULT hr = ::StringFromCLSID(riid,&pOleStr);
if(FAILED(hr))
return false;
int bytesConv = ::WideCharToMultiByte(CP_ACP,0,pOleStr,wcslen(pOleStr),strCLSID,MAX_PATH,NULL,NULL);
CoTaskMemFree(pOleStr);
strCLSID [ bytesConv ] = '';
if(!bytesConv)
{
return false;
}
return true;
}
public:
bool RegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!strlen(ClassId))
return false;
if(!StrFromCLSID(riid,strCLSID))
return false;
if(!strlen(LibId) && strlen(ClassId))
sprintf(Buffer,"%s.%s/CLSID",ClassId,ClassId);
else
sprintf(Buffer,"%s.%s/CLSID",LibId,ClassId);
BOOL result;
result = SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",strCLSID);
if(!result)
return false;
sprintf(Buffer,"CLSID/%s",strCLSID);
char Class [ MAX_PATH ];
sprintf(Class,"%s Class",ClassId);
if(!SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Class))
return false;
sprintf(Class,"%s.%s",LibId,ClassId);
strcat(Buffer,"/ProgId");
return SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Class) ? true:false;
}
bool UnRegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"%s.%s/CLSID",LibId,ClassId);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"%s.%s",LibId,ClassId);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"CLSID/%s/ProgId",strCLSID);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
sprintf(Buffer,"CLSID/%s",strCLSID);
return DelFromRegistry(HKEY_CLASSES_ROOT,Buffer) ? true:false;
}
} ;
class CDllRegistrar : public CRegistrar
{
public:
bool RegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId,LPCSTR Path)
{
if(! CRegistrar::RegisterObject(riid,LibId,ClassId))
return false;
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"CLSID/%s/InProcServer32",strCLSID);
return SetInRegistry(HKEY_CLASSES_ROOT,Buffer,"",Path) ? true:false;
}
bool UnRegisterObject(REFIID riid,LPCSTR LibId,LPCSTR ClassId)
{
char strCLSID [ MAX_PATH ];
char Buffer [ MAX_PATH ];
if(!StrFromCLSID(riid,strCLSID))
return false;
sprintf(Buffer,"CLSID/%s/InProcServer32",strCLSID);
if(!DelFromRegistry(HKEY_CLASSES_ROOT,Buffer))
return false;
return CRegistrar::UnRegisterObject(riid,LibId,ClassId);
}
} ;
#endif