I am doing a project where I use DLL's as run-time modules or plugins. To do this, I use the Windows LoadLibrary()
and FreeLibrary()
API calls to call two functions exported by the DLL. I decided to make a class so dealing with the DLL's would be easier. Is there anything I can add to my class to make it better, is there anything I'm doing wrong? Feel free to criticize anything you want.
SaModule.h
#ifndef SAMODULE_H__
#define SAMODULE_H__
#include <Windows.h>
#include <string>
#include <exception>
#include "WinException.h"
class SaModule
{
private:
typedef const char* (*LPFNGETNAME)();
typedef bool (*LPFNDOSCAN)(std::string&, std::string&);
HINSTANCE hInstance;
std::string path;
public:
SaModule();
SaModule(const std::string& path);
~SaModule();
void Load(const std::string& path);
void Unload();
LPFNDOSCAN DoScan;
LPFNGETNAME GetName;
HINSTANCE GetHandle() const;
operator HINSTANCE() const;
};
#endif//SAMODULE_H__
SaModule.cpp
#include "SaModule.h"
#include "WinException.h"
#include <sstream>
#include <iomanip>
SaModule::SaModule(): path(), hInstance(NULL)
{
//Nothing...
}
SaModule::SaModule(const std::string& path): path(path), hInstance(NULL)
{
Load(path);
}
SaModule::~SaModule()
{
Unload();
}
void SaModule::Load(const std::string& path)
{
this->path = path;
if( NULL == (hInstance=LoadLibrary(path.c_str())) )
throw WinException();
if( NULL == (GetName=reinterpret_cast<LPFNGETNAME>(GetProcAddress(hInstance,"GetName"))) )
throw WinException();
if( NULL == (DoScan=reinterpret_cast<LPFNDOSCAN>(GetProcAddress(hInstance, "DoScan"))) )
throw WinException();
}
void SaModule::Unload()
{
FreeLibrary(hInstance);
}
HINSTANCE SaModule::GetHandle() const
{
return hInstance;
}
SaModule::operator HINSTANCE() const
{
return hInstance;
}
WinException.h
#ifndef WINEXCEPTION_H__
#define WINEXCEPTION_H__
#include <Windows.h>
#include <exception>
#include <string>
class WinException: public std::exception
{
private:
DWORD dwError;
std::string errMsg;
public:
WinException();
const char* what() const;
};
#endif//WINEXCEPTION_H__
WinException.cpp
#include "WinException.h"
#include <sstream>
#include <iomanip>
WinException::WinException()
{
std::ostringstream ss;
dwError = GetLastError();
LPVOID lpMsgBuf = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, NULL);
ss << "Error: 0x" << std::hex << std::setfill('0') << std::setw(8) << dwError << std::endl
<< reinterpret_cast<LPTSTR>(lpMsgBuf);
errMsg = ss.str();
LocalFree(lpMsgBuf);
}
const char* WinException::what() const
{
return errMsg.c_str();
}
Example Usage
#include <iostream>
#include "SaModule.h"
int main(int argc, char* argv[])
{
try
{
SaModule mod("some.sa.dll");
std::cout << "Loaded Module: " << mod.GetName() << std::endl;
}
catch( WinException& ex )
{
std::cout << ex.what() << std::endl;
}
return 0;
}
SAMODULE_H__
cause the identifier to infringe upon the reserved ones. Even if you've seen this, read the double underscores part carefully: stackoverflow.com/questions/228783/… \$\endgroup\$