Ok, I've written this code hundrends of times and I've never had problems before. Can somebody point out what I did wrong?
I'm working on a dll interface template class for my code base, and I'm having a slight problem. After everything is done and the app has returned, I get a bunch of "First-chance exception in Code Base.exe (KERNEL32.DLL): 0xC0000005: Access Violation."
Can someone help me find my error?
The code seems to work fine, up until the app closes.
Here's my code:
//######################################################################
// Log
//######################################################################
void Log(const char* pStream, ...)
{
#ifdef _DEBUG
va_list VaList;
char szBuffer[1024];
va_start(VaList, pStream);
vsprintf(szBuffer, pStream, VaList);
va_end(VaList);
std::ofstream fout("log.txt", std::ios::app);
fout<<szBuffer;
fout.close();
#endif
}
//######################################################################
// DllLoader
//######################################################################
class DllLoader
{
HINSTANCE m_Handle;
std::string m_FileName;
public:
DllLoader()
{
m_Handle = 0;
}
~DllLoader()
{
}
bool Load(const char* pFileName)
{
// If a DLL was already loaded, we'll unload it for the new DLL
if(m_Handle)
Release();
// If a filename wasn't supplied, we'll return false
if(!pFileName)
{
Log("DllLoader::Load() - No filename was supplied.\n");
return false;
}
// Load the library
m_Handle = LoadLibrary(pFileName);
// If the library wasn't loaded (for some reason) then we return false
if(!m_Handle)
{
Log("DllLoader::Load() - Library could not be loaded.\n");
return false;
}
Log("DllLoader::Load() - %s was loaded into memory.\n", pFileName);
m_FileName = pFileName;
return true;
}
void Release()
{
// If the DLL wasn't loaded, we can't unload it. So, we return
if(!m_Handle)
{
Log("DllLoader::Release() - A DLL was never loaded into memory.\n");
return;
}
// Free the library
FreeLibrary(m_Handle);
Log("DllLoader::Release() - %s was released.\n", m_FileName.c_str());
}
template <typename GF_FUNCTYPE>
bool GetFunction(const char* pFuncName, GF_FUNCTYPE& fpFunc)
{
// If a DLL wasn't loaded then return false
if(!m_Handle)
{
Log("DllLoader::GetFunction() - A DLL was never loaded into memory.\n");
return false;
}
// If a function name wasn't supplied, then return false
if(!pFuncName)
{
Log("DllLoader::GetFunction() - A function name was not supplied.\n");
return false;
}
// Get the proc. address
fpFunc = (GF_FUNCTYPE)GetProcAddress(m_Handle, pFuncName);
// If the function failed to load, return false
if(!fpFunc)
{
Log("DllLoader::GetFunction() - %s failed to load.\n", pFuncName);
return false;
}
Log("DllLoader::GetFunction() - %s was loaded into memory.\n", pFuncName);
return true;
}
};
//######################################################################
// DllInterface
//######################################################################
template <typename INTERFACETYPE>
class DllInterface
{
// Type definitions for each INTERFACETYPE
typedef bool (*CREATEINTERFACE)(INTERFACETYPE* pInterface, void* pData);
typedef void (*DESTROYINTERFACE)(INTERFACETYPE* pInterface);
INTERFACETYPE m_pInterface;
DllLoader m_Loader;
public:
DllInterface()
{
m_pInterface = 0;
}
~DllInterface()
{
}
bool Load(const char* pFileName, void* pData)
{
// If we can't load the dll, then return false
if(!m_Loader.Load(pFileName))
return false;
// If we can't load the function, then return false
CREATEINTERFACE CreateInterface = 0;
if(!m_Loader.GetFunction("CreateInterface", CreateInterface))
return false;
// If we fail to create the interface, then return false
if(!CreateInterface(&m_pInterface, pData))
return false;
// The interface was loaded, return true
return true;
}
void Release()
{
// If the interface wasn't loaded, return
if(!m_pInterface)
return;
// If we can't load the DestroyInterface function, then return false
DESTROYINTERFACE DestroyInterface = 0;
if(!m_Loader.GetFunction("DestroyInterface", DestroyInterface))
return;
// Destroy the interface
DestroyInterface(&m_pInterface);
// Release the DLL
m_Loader.Release();
}
INTERFACETYPE GetInterface() const
{
return m_pInterface;
}
};
#include <windows.h>
#include "dftCommon.h"
#include "ITextOut.h"
dftlib::DllInterface<ITextOut*> g_TextOut;
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
g_TextOut.Load("TextOut.dll", 0);
g_TextOut.GetInterface()->DrawText("Test 123");
g_TextOut.Release();
return 0;
}
[/soure]
ITextOut
#ifndef _ITEXTOUT_H_
#define _ITEXTOUT_H_
class ITextOut
{
public:
virtual void DrawText(const char* pString) = 0;
};
#endif
CTextOut.h
#ifndef _TEXTOUT_H_
#define _TEXTOUT_H_
#include <windows.h>
#include "ITextOut.h"
class CTextOut : public ITextOut
{
public:
void DrawText(const char* pString);
};
extern "C" __declspec(dllexport) bool CreateInterface(ITextOut** pTextOut, void* pData);
extern "C" __declspec(dllexport) void DestroyInterface(ITextOut** pTextOut);
#endif
CTextOut.cpp (TextOut.dll)
#include "TextOut.h"
void CTextOut::DrawText(const char* pString)
{
MessageBox(0, pString, "Message", MB_OK);
}
extern "C" __declspec(dllexport) bool CreateInterface(ITextOut** pTextOut, void* pData)
{
if(*pTextOut)
return false;
*pTextOut = new CTextOut;
return *pTextOut != 0;
}
extern "C" __declspec(dllexport) void DestroyInterface(ITextOut** pTextOut)
{
if(!*pTextOut)
return;
delete *pTextOut;
}
Any help would be awesome! Also, any suggestions about fixing some of my code? (Mostly my CreateInterface and DestroyInterface)
Thanks!